library(swimplot) library(grid) library(gtable) library(readr) library(mosaic) library(dplyr) library(survival) library(survminer) library(ggplot2) library(scales) library(coxphf) library(ggthemes) library(tidyverse) library(gtsummary) library(flextable) library(parameters) library(car) library(ComplexHeatmap) library(rms)

#ctDNA positivity by stage and window

#ctDNA at MRD
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.MRD!="",]
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
circ_data <- subset(circ_data, ctDNA.MRD %in% c("NEGATIVE", "POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("II","III","IV"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.MRD == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.MRD, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.MRD == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#ctDNA C5D1
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.C5D1!="",]
circ_data$ctDNA.C5D1 <- factor(circ_data$ctDNA.C5D1, levels=c("NEGATIVE","POSITIVE"))
circ_data <- subset(circ_data, ctDNA.C5D1 %in% c("NEGATIVE", "POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("II","III","IV"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.C5D1 == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.C5D1, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.C5D1 == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#ctDNA C8D1
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.C8D1!="",]
circ_data$ctDNA.C8D1 <- factor(circ_data$ctDNA.C8D1, levels=c("NEGATIVE","POSITIVE"))
circ_data <- subset(circ_data, ctDNA.C8D1 %in% c("NEGATIVE", "POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("II","III","IV"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.C8D1 == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.C8D1, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.C8D1 == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#ctDNA EOT
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.EOT!="",]
circ_data$ctDNA.EOT <- factor(circ_data$ctDNA.EOT, levels=c("NEGATIVE","POSITIVE"))
circ_data <- subset(circ_data, ctDNA.EOT %in% c("NEGATIVE", "POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("II","III","IV"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.EOT == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.EOT, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.EOT == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#ctDNA anytime
rm(list=ls())
setwd("~/Downloads")
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.anytime!="",]
circ_data$ctDNA.anytime <- factor(circ_data$ctDNA.anytime, levels=c("NEGATIVE","POSITIVE"))
circ_data <- subset(circ_data, ctDNA.anytime %in% c("NEGATIVE", "POSITIVE"))
circ_data$Stage <- factor(circ_data$Stage, levels=c("II","III","IV"))
positive_counts_by_stage <- aggregate(circ_data$ctDNA.anytime == "POSITIVE", by=list(circ_data$Stage), FUN=sum)
total_counts_by_stage <- aggregate(circ_data$ctDNA.anytime, by=list(circ_data$Stage), FUN=length)
combined_data <- data.frame(
  Stage = total_counts_by_stage$Group.1,
  Total_Count = total_counts_by_stage$x,
  Positive_Count = positive_counts_by_stage$x,
  Rate = (positive_counts_by_stage$x / total_counts_by_stage$x) * 100  # Convert to percentage
)
combined_data$Rate <- sprintf("%.2f%%", combined_data$Rate)
overall_total_count <- nrow(circ_data)
overall_positive_count <- nrow(circ_data[circ_data$ctDNA.anytime == "POSITIVE",])
overall_positivity_rate <- (overall_positive_count / overall_total_count) * 100  # Convert to percentage
overall_row <- data.frame(
  Stage = "Overall",
  Total_Count = overall_total_count,
  Positive_Count = overall_positive_count,
  Rate = sprintf("%.2f%%", overall_positivity_rate)
)
combined_data <- rbind(combined_data, overall_row)
print(combined_data)

#Heatmap for clinicopathologic factors

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_datadf <- as.data.frame(circ_data)
circ_data <- circ_data %>% arrange(Stage)
circ_datadf <- as.data.frame(circ_data)

ha <- HeatmapAnnotation(
  Stage = circ_data$Stage,
  Sex = circ_data$Sex,
  PrimSite = circ_data$PrimSite,
  pT = circ_data$pT,
  Pathology = circ_data$Pathology,
  Chemo = circ_data$Chemo,
  ctDNA.MRD = circ_data$ctDNA.MRD,
  ctDNA.C5D1 = circ_data$ctDNA.C5D1,
  ctDNA.C8D1 = circ_data$ctDNA.C8D1,
  ctDNA.EOT = circ_data$ctDNA.EOT,
  ctDNA.anytime = circ_data$ctDNA.anytime,
  RecStatus = circ_data$RecStatus,
  VitalStatus = circ_data$VitalStatus,
  
    col = list(Stage = c("II" = "seagreen2", "III" = "orange", "IV" = "purple"),
    Sex = c("Female" = "goldenrod" , "Male" = "blue4"),
    PrimSite = c("pCCA" = "darkgreen", "dCCA" ="#008BCE"),
    pT = c("T1" = "lightblue", "T2" ="orange", "T3" = "brown" ),
    Pathology = c("G1" = "yellow3", "G2" ="darkgreen", "G3" = "brown2"),
    Chemo = c("CAP" = "lightblue", "GemCis" = "orange2"),
    ctDNA.MRD = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.C5D1 = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.C8D1 = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.EOT = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    ctDNA.anytime = c("POSITIVE" = "red3", "NEGATIVE" ="blue"),
    RFS.Event = c("TRUE" = "red3", "FALSE" ="blue"),
    OS.Event = c("TRUE" = "black", "FALSE" ="grey")
)
)
ht <- Heatmap(matrix(nrow = 0, ncol = length(circ_data$Stage)),show_row_names = FALSE,cluster_rows = F,cluster_columns = FALSE, top_annotation = ha)
pdf("heatmap.pdf",width = 7, height = 7)
draw(ht, annotation_legend_side = "bottom")
dev.off()
null device 
          1 

#Prognostic role of ctDNA at the MRD time point

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 67     45  15.84   11.96    27.6
ctDNA.MRD=POSITIVE 22     20   8.23    7.86    15.5
event_summary <- circ_data %>%
  group_by(ctDNA.MRD) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="DFS - ctDNA MRD timepoint", ylab= "Disease Free Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     38      28    0.577  0.0607        0.450        0.686
   24     26      11    0.407  0.0608        0.288        0.523

                ctDNA.MRD=POSITIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12      7      15    0.318  0.0993       0.1418        0.511
   24      5       2    0.227  0.0893       0.0827        0.414
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 89, number of events= 65 

                    coef exp(coef) se(coef)     z Pr(>|z|)  
ctDNA.MRDPOSITIVE 0.5902    1.8043   0.2705 2.182   0.0291 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     1.804     0.5542     1.062     3.066

Concordance= 0.556  (se = 0.028 )
Likelihood ratio test= 4.38  on 1 df,   p=0.04
Wald test            = 4.76  on 1 df,   p=0.03
Score (logrank) test = 4.9  on 1 df,   p=0.03
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 1.8 (1.06-3.07); p = 0.029"

#OS by ctDNA at the MRD time point

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data$OS.months=circ_data$OS.months-2
circ_data <- circ_data[circ_data$OS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$OS.months, event = circ_data$OS.Event)~ctDNA.MRD, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$OS.months, event = circ_data$OS.Event) ~ 
    ctDNA.MRD, data = circ_data)

                    n events median 0.95LCL 0.95UCL
ctDNA.MRD=NEGATIVE 67     39   38.5    28.9      NA
ctDNA.MRD=POSITIVE 22     17   30.8    22.6      NA
event_summary <- circ_data %>%
  group_by(ctDNA.MRD) %>%
  summarise(
    Total = n(),
    Events = sum(OS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$OS.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.MRD, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA MRD timepoint", ylab= "Overall Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.MRD, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.MRD=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     65       2    0.970  0.0208        0.886        0.992
   24     50      15    0.746  0.0532        0.624        0.834

                ctDNA.MRD=POSITIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     17       5    0.773  0.0893        0.537        0.898
   24     14       3    0.636  0.1026        0.403        0.799
circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.MRD, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.MRD, data = circ_data)

  n= 89, number of events= 56 

                    coef exp(coef) se(coef)     z Pr(>|z|)
ctDNA.MRDPOSITIVE 0.4209    1.5234   0.2911 1.446    0.148

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.MRDPOSITIVE     1.523     0.6564     0.861     2.695

Concordance= 0.54  (se = 0.032 )
Likelihood ratio test= 1.97  on 1 df,   p=0.2
Wald test            = 2.09  on 1 df,   p=0.1
Score (logrank) test = 2.12  on 1 df,   p=0.1
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 1.52 (0.86-2.7); p = 0.148"

#Association of ctDNA MRD MTM levels with clinicopathological factors

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")

tally(~pN, data=circ_data, margins = TRUE)
pN
   N1    N2 Total 
   69    20    89 
circ_data$pN <- factor(circ_data$pN, levels = c("N1","N2"), labels = c("pN1 (n=69)","pN2 (n=20)"))
boxplot(ctDNA.MRD.MTM~pN, data=circ_data, main="ctDNA MRD MTM - pN", xlab="pN", ylab="MTM/mL", col="white",border="black", ylim=c(0, 10))

m1<-wilcox.test(ctDNA.MRD.MTM ~ pN, data=circ_data, na.rm=TRUE, exact=FALSE, conf.int=TRUE)
print(m1)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.MRD.MTM by pN
W = 441.5, p-value = 0.001285
alternative hypothesis: true location shift is not equal to 0
95 percent confidence interval:
 -3.700528e-01 -2.534813e-05
sample estimates:
difference in location 
           -4.5909e-05 
tally(~ResMarg, data=circ_data, margins = TRUE)
ResMarg
   R0    R1 Total 
   60    29    89 
circ_data$ResMarg <- factor(circ_data$ResMarg, levels = c("R0","R1"), labels = c("R0 (n=60)","R1 (n=29)"))
boxplot(ctDNA.MRD.MTM~ResMarg, data=circ_data, main="ctDNA MRD MTM - Resection Margin", 
        xlab="ResMarg", ylab="MTM/mL", col="white", border="black", ylim=c(0, 10))

m2 <- wilcox.test(ctDNA.MRD.MTM ~ ResMarg, data=circ_data, na.rm=TRUE, exact=FALSE, conf.int=TRUE)
print(m2)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.MRD.MTM by ResMarg
W = 637.5, p-value = 0.007319
alternative hypothesis: true location shift is not equal to 0
95 percent confidence interval:
 -0.1700429119 -0.0000566823
sample estimates:
difference in location 
         -7.789783e-05 
tally(~PrimSite, data=circ_data, margins = TRUE)
PrimSite
 dCCA  pCCA Total 
   46    43    89 
circ_data$PrimSite <- factor(circ_data$PrimSite, levels = c("pCCA","dCCA"), labels = c("pCCA (n=43)","dCCA (n=46)"))
boxplot(ctDNA.MRD.MTM~PrimSite, data=circ_data, main="ctDNA MRD MTM - Primary Site", 
        xlab="Primary Site", ylab="MTM/mL", col="white", border="black", ylim=c(0, 10))

m3 <- wilcox.test(ctDNA.MRD.MTM ~ PrimSite, data=circ_data, na.rm=TRUE, exact=FALSE, conf.int=TRUE)
print(m3)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.MRD.MTM by PrimSite
W = 996, p-value = 0.9438
alternative hypothesis: true location shift is not equal to 0
95 percent confidence interval:
 -2.850159e-05  9.561474e-06
sample estimates:
difference in location 
          4.711544e-05 
tally(~Stage, data=circ_data, margins = TRUE)
Stage
   II   III    IV Total 
   38    39    12    89 
circ_data$ctDNA.MRD.MTM <- as.numeric(as.character(circ_data$ctDNA.MRD.MTM))
circ_data$Stage <- factor(circ_data$Stage, levels = c("II","III","IV"), labels = c("II (n=37)", "III (n=40)","IV (n=12)"))
boxplot(ctDNA.MRD.MTM~Stage, data=circ_data, main="ctDNA MRD MTM - Stage", 
        xlab="Stage", ylab="MTM/mL", col="white", border="black", ylim=c(0, 10))

kruskal_result <- kruskal.test(ctDNA.MRD.MTM ~ Stage, data=circ_data)
print(kruskal_result)

    Kruskal-Wallis rank sum test

data:  ctDNA.MRD.MTM by Stage
Kruskal-Wallis chi-squared = 2.8384, df = 2, p-value = 0.2419
pairwise_wilcox <- pairwise.wilcox.test(circ_data$ctDNA.MRD.MTM, circ_data$Stage, 
                                        p.adjust.method = "BH", na.rm = TRUE)
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
Warning in wilcox.test.default(xi, xj, paired = paired, ...) :
  cannot compute exact p-value with ties
print(pairwise_wilcox)

    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  circ_data$ctDNA.MRD.MTM and circ_data$Stage 

           II (n=37) III (n=40)
III (n=40) 0.46      -         
IV (n=12)  0.30      0.39      

P value adjustment method: BH 
tally(~CA19.MRD, data=circ_data, margins = TRUE)
CA19.MRD
Elevated   Normal    Total 
      15       74       89 
circ_data$CA19.MRD <- factor(circ_data$CA19.MRD, levels = c("Normal","Elevated"), labels = c("Normal (n=74)","Elevated (n=15)"))
boxplot(ctDNA.MRD.MTM~CA19.MRD, data=circ_data, main="ctDNA MRD MTM - CA 19-9", 
        xlab="CA 19-9", ylab="MTM/mL", col="white", border="black", ylim=c(0, 10))

m4 <- wilcox.test(ctDNA.MRD.MTM ~ CA19.MRD, data=circ_data, na.rm=TRUE, exact=FALSE, conf.int=TRUE)
print(m4)

    Wilcoxon rank sum test with continuity correction

data:  ctDNA.MRD.MTM by CA19.MRD
W = 371.5, p-value = 0.00808
alternative hypothesis: true location shift is not equal to 0
95 percent confidence interval:
 -2.000269e-01 -4.645475e-05
sample estimates:
difference in location 
         -5.786662e-06 

#Median MTM/mL levels for ctDNA positive pts at MRD

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.MRD=="POSITIVE",]

median_ctDNA <- median(circ_data$ctDNA.MRD.MTM, na.rm = TRUE)
range_ctDNA <- range(circ_data$ctDNA.MRD.MTM, na.rm = TRUE)
cat("Median MTM/mL post-surgery:", median_ctDNA, "\n")
Median MTM/mL post-surgery: 0.605 
cat("Range MTM/mL post-surgery:", range_ctDNA[1], "-", range_ctDNA[2], "\n")
Range MTM/mL post-surgery: 0.1 - 73.04 

#Association of ctDNA MRD status with clinicopathological factors

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels = c("NEGATIVE", "POSITIVE"), labels = c("ctDNA(-)", "ctDNA(+)"))
circ_data$pN <- factor(circ_data$pN, levels = c("N1", "N2"), labels = c("pN1", "pN2"))
contingency_table <- table(circ_data$pN, circ_data$ctDNA.MRD)
chi_square_test <- chisq.test(contingency_table)
Warning in chisq.test(contingency_table) :
  Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 7.1944, df = 1, p-value = 0.007313
fisher_exact_test <- fisher.test(contingency_table)
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.006385
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
  1.403411 15.830714
sample estimates:
odds ratio 
  4.647239 
print(contingency_table)
     
      ctDNA(-) ctDNA(+)
  pN1       57       12
  pN2       10       10
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2
ggplot(table_df, aes(x = Var1, y = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(y = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA status - pN", 
       x = "pN", 
       y = "Patients (%)", 
       fill = "ctDNA MRD",
       caption = paste("Fisher's exact test p-value: ", format.pval(fisher_exact_test$p.value))) +
  scale_y_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("ctDNA(-)" = "blue", "ctDNA(+)" = "red")) + # define custom colors
  theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 14), # increase x-axis text size
        axis.text.y = element_text(size = 14, color = "black"), # increase y-axis text size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Progression label size


rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels = c("NEGATIVE", "POSITIVE"), labels = c("ctDNA(-)", "ctDNA(+)"))
circ_data$ResMarg <- factor(circ_data$ResMarg, levels = c("R0", "R1"), labels = c("R0", "R1"))
contingency_table <- table(circ_data$ResMarg, circ_data$ctDNA.MRD)
chi_square_test <- chisq.test(contingency_table)
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 5.1569, df = 1, p-value = 0.02315
fisher_exact_test <- fisher.test(contingency_table)
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.01762
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
  1.146895 10.855465
sample estimates:
odds ratio 
  3.472855 
print(contingency_table)
    
     ctDNA(-) ctDNA(+)
  R0       50       10
  R1       17       12
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2
ggplot(table_df, aes(x = Var1, y = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(y = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA status - Margins", 
       x = "Margins", 
       y = "Patients (%)", 
       fill = "ctDNA MRD",
       caption = paste("Fisher's exact test p-value: ", format.pval(fisher_exact_test$p.value))) +
  scale_y_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("ctDNA(-)" = "blue", "ctDNA(+)" = "red")) + # define custom colors
  theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 14), # increase x-axis text size
        axis.text.y = element_text(size = 14, color = "black"), # increase y-axis text size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Progression label size


rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels = c("NEGATIVE", "POSITIVE"), labels = c("ctDNA(-)", "ctDNA(+)"))
circ_data$PrimSite <- factor(circ_data$PrimSite, levels = c("pCCA", "dCCA"), labels = c("pCCA", "dCCA"))
contingency_table <- table(circ_data$PrimSite, circ_data$ctDNA.MRD)
chi_square_test <- chisq.test(contingency_table)
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 0, df = 1, p-value = 1
fisher_exact_test <- fisher.test(contingency_table)
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 1
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
 0.3114469 2.6872455
sample estimates:
odds ratio 
 0.9152081 
print(contingency_table)
      
       ctDNA(-) ctDNA(+)
  pCCA       32       11
  dCCA       35       11
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2
ggplot(table_df, aes(x = Var1, y = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(y = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA status - Primary Site", 
       x = "Primary Site", 
       y = "Patients (%)", 
       fill = "ctDNA MRD",
       caption = paste("Fisher's exact test p-value: ", format.pval(fisher_exact_test$p.value))) +
  scale_y_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("ctDNA(-)" = "blue", "ctDNA(+)" = "red")) + # define custom colors
  theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 14), # increase x-axis text size
        axis.text.y = element_text(size = 14, color = "black"), # increase y-axis text size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Progression label size


rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels = c("NEGATIVE", "POSITIVE"), labels = c("ctDNA(-)", "ctDNA(+)"))
circ_data$Stage <- factor(circ_data$Stage, levels = c("II", "III", "IV"), labels = c("II", "III", "IV"))
contingency_table <- table(circ_data$Stage, circ_data$ctDNA.MRD)
chi_square_test <- chisq.test(contingency_table)
Warning in chisq.test(contingency_table) :
  Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test

data:  contingency_table
X-squared = 2.68, df = 2, p-value = 0.2619
fisher_exact_test <- fisher.test(contingency_table)
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.2546
alternative hypothesis: two.sided
print(contingency_table)
     
      ctDNA(-) ctDNA(+)
  II        31        7
  III       29       10
  IV         7        5
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2
ggplot(table_df, aes(x = Var1, y = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(y = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA status - Stage", 
       x = "Stage", 
       y = "Patients (%)", 
       fill = "ctDNA MRD",
       caption = paste("Fisher's exact test p-value: ", format.pval(fisher_exact_test$p.value))) +
  scale_y_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("ctDNA(-)" = "blue", "ctDNA(+)" = "red")) + # define custom colors
  theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 14), # increase x-axis text size
        axis.text.y = element_text(size = 14, color = "black"), # increase y-axis text size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Progression label size


pairwise_fisher <- function(data, factor1, factor2) {
  levels <- unique(data[[factor1]])
  results <- data.frame(Stage1 = character(), Stage2 = character(), p.value = numeric(), stringsAsFactors = FALSE)
  
  for (i in 1:(length(levels) - 1)) {
    for (j in (i + 1):length(levels)) {
      subset_data <- data %>% filter(data[[factor1]] %in% c(levels[i], levels[j]))
      contingency_table_pairwise <- table(subset_data[[factor1]], subset_data[[factor2]])
      fisher_result <- fisher.test(contingency_table_pairwise)
      results <- rbind(results, data.frame(Stage1 = levels[i], Stage2 = levels[j], p.value = fisher_result$p.value))
    }
  }
  return(results)
}

# Perform pairwise comparisons
pairwise_results <- pairwise_fisher(circ_data, "Stage", "ctDNA.MRD")
print(pairwise_results)

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")

circ_data$ctDNA.MRD <- factor(circ_data$ctDNA.MRD, levels = c("NEGATIVE", "POSITIVE"), labels = c("ctDNA(-)", "ctDNA(+)"))
circ_data$CA19.MRD <- factor(circ_data$CA19.MRD, levels = c("Normal", "Elevated"), labels = c("Normal", "Elevated"))
contingency_table <- table(circ_data$CA19.MRD, circ_data$ctDNA.MRD)
chi_square_test <- chisq.test(contingency_table)
Warning in chisq.test(contingency_table) :
  Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 6.1961, df = 1, p-value = 0.0128
fisher_exact_test <- fisher.test(contingency_table)
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.008766
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
  1.282588 18.543083
sample estimates:
odds ratio 
  4.787433 
print(contingency_table)
          
           ctDNA(-) ctDNA(+)
  Normal         60       14
  Elevated        7        8
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2
ggplot(table_df, aes(x = Var1, y = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(y = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA status - CA 19-9", 
       x = "CA 19-9", 
       y = "Patients (%)", 
       fill = "ctDNA MRD",
       caption = paste("Fisher's exact test p-value: ", format.pval(fisher_exact_test$p.value))) +
  scale_y_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("ctDNA(-)" = "blue", "ctDNA(+)" = "red")) + # define custom colors
  theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 14), # increase x-axis text size
        axis.text.y = element_text(size = 14, color = "black"), # increase y-axis text size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Progression label size

#Prognostic role of ctDNA at C5D1

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.C5D1!="",]
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.C5D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.C5D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C5D1=NEGATIVE 71     48   15.9   12.92   27.57
ctDNA.C5D1=POSITIVE 17     17    4.8    3.09    7.86
event_summary <- circ_data %>%
  group_by(ctDNA.C5D1) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C5D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="DFS - ctDNA C5D1", ylab= "Disease Free Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C5D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C5D1=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     43      27    0.615  0.0581        0.491        0.717
   24     30      12    0.441  0.0596        0.323        0.553

                ctDNA.C5D1=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
    12.00000      1.00000     16.00000      0.05882      0.05707      0.00391      0.23501 
circ_data$ctDNA.C5D1 <- factor(circ_data$ctDNA.C5D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C5D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C5D1, data = circ_data)

  n= 88, number of events= 65 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.C5D1POSITIVE 2.0439    7.7207   0.3238 6.312 2.76e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C5D1POSITIVE     7.721     0.1295     4.093     14.56

Concordance= 0.638  (se = 0.026 )
Likelihood ratio test= 31.63  on 1 df,   p=2e-08
Wald test            = 39.84  on 1 df,   p=3e-10
Score (logrank) test = 53.01  on 1 df,   p=3e-13
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 7.72 (4.09-14.56); p = 0"

#Multivariate regression model for DFS with ctDNA and CA 19-9

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
circ_datadf <- as.data.frame(circ_data)
circ_datadf$Sex <- factor(circ_datadf$Sex, levels = c("Female", "Male"), labels = c("Female", "Male"))
circ_datadf$PrimSite <- factor(circ_datadf$PrimSite, levels = c("pCCA", "dCCA"), labels = c("pCCA", "dCCA"))
circ_datadf$Chemo <- factor(circ_datadf$Chemo, levels = c("CAP", "GemCis"), labels = c("CAP", "GemCis"))
circ_datadf$ResMarg <- factor(circ_datadf$ResMarg, levels = c("R0", "R1"))
circ_datadf$Stage <- factor(circ_datadf$Stage, levels = c("II", "III", "IV"), labels = c("II", "III", "IV"))
circ_datadf$TP53 <- factor(circ_datadf$TP53, levels = c("WT", "Mut"))
circ_datadf$CA19.C5D1 <- factor(circ_datadf$CA19.C5D1, levels = c("Normal", "Elevated"))
circ_datadf$ctDNA.C5D1 <- factor(circ_datadf$ctDNA.C5D1, levels = c("NEGATIVE", "POSITIVE"), labels = c("Negative", "Positive"))
surv_object<-Surv(time = circ_datadf$RFS.months, event = circ_datadf$RFS.Event) 
cox_fit <- coxph(surv_object ~ Sex + Age + PrimSite + Stage + Chemo + ResMarg + CA19.C5D1 + ctDNA.C5D1, data=circ_datadf) 
ggforest(cox_fit, data = circ_datadf, main = "Multivariate Regression Model for DFS - Landmark analysis", refLabel = "Reference Group")

test.ph <- cox.zph(cox_fit)

#Univariate regression model for factors used at the C5D1 MVA

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
circ_data$Sex <- factor(circ_data$Sex, levels = c("Female", "Male"), labels = c("Female", "Male")) #univariate for gender
cox_fit <- coxph(surv_object ~ Sex, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ Sex, data = circ_data)

  n= 89, number of events= 65 

          coef exp(coef) se(coef)     z Pr(>|z|)
SexMale 0.1594    1.1728   0.2689 0.593    0.553

        exp(coef) exp(-coef) lower .95 upper .95
SexMale     1.173     0.8527    0.6923     1.987

Concordance= 0.515  (se = 0.031 )
Likelihood ratio test= 0.36  on 1 df,   p=0.5
Wald test            = 0.35  on 1 df,   p=0.6
Score (logrank) test = 0.35  on 1 df,   p=0.6
cox_fit_summary <- summary(cox_fit)
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 1.17 (0.69-1.99); p = 0.553"
rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
cox_fit <- coxph(surv_object ~ Age, data=circ_data) #univariate for age
summary(cox_fit)
Call:
coxph(formula = surv_object ~ Age, data = circ_data)

  n= 89, number of events= 65 

        coef exp(coef) se(coef)     z Pr(>|z|)
Age 0.002393  1.002396 0.019228 0.124    0.901

    exp(coef) exp(-coef) lower .95 upper .95
Age     1.002     0.9976    0.9653     1.041

Concordance= 0.493  (se = 0.041 )
Likelihood ratio test= 0.02  on 1 df,   p=0.9
Wald test            = 0.02  on 1 df,   p=0.9
Score (logrank) test = 0.02  on 1 df,   p=0.9
cox_fit_summary <- summary(cox_fit)
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 1 (0.97-1.04); p = 0.901"
rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
circ_data$PrimSite <- factor(circ_data$PrimSite, levels = c("pCCA", "dCCA"), labels = c("pCCA", "dCCA")) #univariate for Primary Site
cox_fit <- coxph(surv_object ~ PrimSite, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ PrimSite, data = circ_data)

  n= 89, number of events= 65 

                coef exp(coef) se(coef)      z Pr(>|z|)  
PrimSitedCCA -0.4558    0.6340   0.2520 -1.809   0.0705 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

             exp(coef) exp(-coef) lower .95 upper .95
PrimSitedCCA     0.634      1.577    0.3869     1.039

Concordance= 0.535  (se = 0.034 )
Likelihood ratio test= 3.31  on 1 df,   p=0.07
Wald test            = 3.27  on 1 df,   p=0.07
Score (logrank) test = 3.33  on 1 df,   p=0.07
cox_fit_summary <- summary(cox_fit)
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 0.63 (0.39-1.04); p = 0.071"
rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ Stage, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = TRUE, conf.int = FALSE, risk.table = TRUE, break.time.by=3, palette=c("blue","green","red"), title="DFS - ctDNA C5D1 - Stage", ylab= "Disease Free Survival", xlab="Time (Months)", legend.labs=c("II", "III", "IV"), legend.title="")

circ_data$Stage <- factor(circ_data$Stage, levels = c("II", "III", "IV"), labels = c("II", "III", "IV")) #univariate for Stage
cox_fit <- coxph(surv_object ~ Stage, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ Stage, data = circ_data)

  n= 89, number of events= 65 

           coef exp(coef) se(coef)     z Pr(>|z|)   
StageIII 0.2297    1.2583   0.2777 0.827  0.40805   
StageIV  1.1237    3.0761   0.3631 3.095  0.00197 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

         exp(coef) exp(-coef) lower .95 upper .95
StageIII     1.258     0.7947    0.7301     2.168
StageIV      3.076     0.3251    1.5099     6.267

Concordance= 0.565  (se = 0.037 )
Likelihood ratio test= 8.34  on 2 df,   p=0.02
Wald test            = 9.93  on 2 df,   p=0.007
Score (logrank) test = 10.77  on 2 df,   p=0.005
rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
circ_data$Chemo <- factor(circ_data$Chemo, levels = c("CAP", "GemCis"), labels = c("CAP", "GemCis")) #univariate for Chemotherapy
cox_fit <- coxph(surv_object ~ Chemo, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ Chemo, data = circ_data)

  n= 89, number of events= 65 

                coef exp(coef) se(coef)      z Pr(>|z|)
ChemoGemCis -0.02437   0.97592  0.24846 -0.098    0.922

            exp(coef) exp(-coef) lower .95 upper .95
ChemoGemCis    0.9759      1.025    0.5997     1.588

Concordance= 0.507  (se = 0.034 )
Likelihood ratio test= 0.01  on 1 df,   p=0.9
Wald test            = 0.01  on 1 df,   p=0.9
Score (logrank) test = 0.01  on 1 df,   p=0.9
cox_fit_summary <- summary(cox_fit)
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 0.98 (0.6-1.59); p = 0.922"
rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
circ_data$ResMarg <- factor(circ_data$ResMarg, levels = c("R0", "R1")) #univariate for Resection margin
cox_fit <- coxph(surv_object ~ ResMarg, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ResMarg, data = circ_data)

  n= 89, number of events= 65 

            coef exp(coef) se(coef)     z Pr(>|z|)
ResMargR1 0.3415    1.4071   0.2617 1.305    0.192

          exp(coef) exp(-coef) lower .95 upper .95
ResMargR1     1.407     0.7107    0.8425      2.35

Concordance= 0.534  (se = 0.03 )
Likelihood ratio test= 1.64  on 1 df,   p=0.2
Wald test            = 1.7  on 1 df,   p=0.2
Score (logrank) test = 1.72  on 1 df,   p=0.2
cox_fit_summary <- summary(cox_fit)
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 1.41 (0.84-2.35); p = 0.192"
rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
circ_data$CA19.C5D1 <- factor(circ_data$CA19.C5D1, levels = c("Normal", "Elevated")) #univariate for CA 19-9 C5D1
cox_fit <- coxph(surv_object ~ CA19.C5D1, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ CA19.C5D1, data = circ_data)

  n= 80, number of events= 56 
   (9 observations deleted due to missingness)

                    coef exp(coef) se(coef)     z Pr(>|z|)
CA19.C5D1Elevated 0.2218    1.2483   0.3264 0.679    0.497

                  exp(coef) exp(-coef) lower .95 upper .95
CA19.C5D1Elevated     1.248     0.8011    0.6584     2.367

Concordance= 0.535  (se = 0.032 )
Likelihood ratio test= 0.44  on 1 df,   p=0.5
Wald test            = 0.46  on 1 df,   p=0.5
Score (logrank) test = 0.46  on 1 df,   p=0.5
cox_fit_summary <- summary(cox_fit)
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 1.25 (0.66-2.37); p = 0.497"
rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
circ_data$ctDNA.C5D1 <- factor(circ_data$ctDNA.C5D1, levels = c("NEGATIVE", "POSITIVE"), labels = c("Negative", "Positive")) #univariate for ctDNA C5D1
cox_fit <- coxph(surv_object ~ ctDNA.C5D1, data=circ_data)
summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C5D1, data = circ_data)

  n= 88, number of events= 65 
   (1 observation deleted due to missingness)

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.C5D1Positive 2.0439    7.7207   0.3238 6.312 2.76e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C5D1Positive     7.721     0.1295     4.093     14.56

Concordance= 0.638  (se = 0.026 )
Likelihood ratio test= 31.63  on 1 df,   p=2e-08
Wald test            = 39.84  on 1 df,   p=3e-10
Score (logrank) test = 53.01  on 1 df,   p=3e-13
cox_fit_summary <- summary(cox_fit)
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 7.72 (4.09-14.56); p = 0"

#OS by ctDNA at C5D1

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.C5D1!="",]
circ_data$OS.months=circ_data$OS.months-2
circ_data <- circ_data[circ_data$OS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$OS.months, event = circ_data$OS.Event)~ctDNA.C5D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$OS.months, event = circ_data$OS.Event) ~ 
    ctDNA.C5D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C5D1=NEGATIVE 71     39   44.8    31.7      NA
ctDNA.C5D1=POSITIVE 17     17   18.4    13.1    35.3
event_summary <- circ_data %>%
  group_by(ctDNA.C5D1) %>%
  summarise(
    Total = n(),
    Events = sum(OS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$OS.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C5D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA C5D1", ylab= "Overall Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C5D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C5D1=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     69       2    0.972  0.0196        0.892        0.993
   24     56      13    0.789  0.0484        0.674        0.867

                ctDNA.C5D1=POSITIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     12       5    0.706   0.111        0.431        0.866
   24      7       5    0.412   0.119        0.186        0.626
circ_data$ctDNA.C5D1 <- factor(circ_data$ctDNA.C5D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C5D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C5D1, data = circ_data)

  n= 88, number of events= 56 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.C5D1POSITIVE 1.2634    3.5375   0.2983 4.235 2.29e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C5D1POSITIVE     3.537     0.2827     1.971     6.348

Concordance= 0.603  (se = 0.029 )
Likelihood ratio test= 14.98  on 1 df,   p=1e-04
Wald test            = 17.93  on 1 df,   p=2e-05
Score (logrank) test = 20.38  on 1 df,   p=6e-06
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 3.54 (1.97-6.35); p = 0"

#Prognostic role of ctDNA at C8D1

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.C8D1!="",]
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.C8D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.C8D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C8D1=NEGATIVE 62     40  17.02   13.84    33.4
ctDNA.C8D1=POSITIVE 15     15   7.13    5.36    15.2
event_summary <- circ_data %>%
  group_by(ctDNA.C8D1) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C8D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="DFS - ctDNA C8D1", ylab= "Disease Free Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C8D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C8D1=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     40      22    0.645  0.0608        0.513        0.750
   24     29      10    0.481  0.0637        0.353        0.599

                ctDNA.C8D1=POSITIVE 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     12.0000       3.0000      12.0000       0.2000       0.1033       0.0489       0.4239 
circ_data$ctDNA.C8D1 <- factor(circ_data$ctDNA.C8D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C8D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C8D1, data = circ_data)

  n= 77, number of events= 55 

                     coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.C8D1POSITIVE 1.6561    5.2389   0.3281 5.047 4.49e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C8D1POSITIVE     5.239     0.1909     2.754     9.967

Concordance= 0.624  (se = 0.028 )
Likelihood ratio test= 20.53  on 1 df,   p=6e-06
Wald test            = 25.47  on 1 df,   p=4e-07
Score (logrank) test = 31.38  on 1 df,   p=2e-08
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 5.24 (2.75-9.97); p = 0"

#OS by ctDNA at C8D1

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.C8D1!="",]
circ_data$OS.months=circ_data$OS.months-2
circ_data <- circ_data[circ_data$OS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$OS.months, event = circ_data$OS.Event)~ctDNA.C8D1, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$OS.months, event = circ_data$OS.Event) ~ 
    ctDNA.C8D1, data = circ_data)

                     n events median 0.95LCL 0.95UCL
ctDNA.C8D1=NEGATIVE 62     32   48.4    30.1      NA
ctDNA.C8D1=POSITIVE 15     15   29.8    17.5    41.8
event_summary <- circ_data %>%
  group_by(ctDNA.C8D1) %>%
  summarise(
    Total = n(),
    Events = sum(OS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$OS.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C8D1, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA C8D1", ylab= "Overall Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C8D1, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.C8D1=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     60       2    0.968  0.0224        0.877        0.992
   24     48      12    0.774  0.0531        0.649        0.860

                ctDNA.C8D1=POSITIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     13       2    0.867  0.0878        0.564        0.965
   24      8       5    0.533  0.1288        0.263        0.744
circ_data$ctDNA.C8D1 <- factor(circ_data$ctDNA.C8D1, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.C8D1, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C8D1, data = circ_data)

  n= 77, number of events= 47 

                     coef exp(coef) se(coef)     z Pr(>|z|)   
ctDNA.C8D1POSITIVE 1.0300    2.8011   0.3192 3.227  0.00125 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                   exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C8D1POSITIVE     2.801      0.357     1.499     5.236

Concordance= 0.574  (se = 0.031 )
Likelihood ratio test= 9.08  on 1 df,   p=0.003
Wald test            = 10.42  on 1 df,   p=0.001
Score (logrank) test = 11.35  on 1 df,   p=8e-04
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 2.8 (1.5-5.24); p = 0.001"

#Prognostic role of ctDNA anytime post-surgery

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.anytime!="",]
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.anytime, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.anytime, data = circ_data)

                        n events median 0.95LCL 0.95UCL
ctDNA.anytime=NEGATIVE 42     20  38.71   19.06      NA
ctDNA.anytime=POSITIVE 47     45   8.05    7.56      12
event_summary <- circ_data %>%
  group_by(ctDNA.anytime) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.anytime, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="DFS - ctDNA anytime post-surgery", ylab= "Disease Free Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.anytime, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.anytime=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     30      11    0.734  0.0689        0.571        0.843
   24     24       5    0.609  0.0766        0.442        0.739

                ctDNA.anytime=POSITIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     15      32    0.319  0.0680       0.1928        0.453
   24      7       8    0.149  0.0519       0.0655        0.264
circ_data$ctDNA.anytime <- factor(circ_data$ctDNA.anytime, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.anytime, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.anytime, data = circ_data)

  n= 89, number of events= 65 

                        coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.anytimePOSITIVE 1.3374    3.8090   0.2757 4.851 1.23e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                      exp(coef) exp(-coef) lower .95 upper .95
ctDNA.anytimePOSITIVE     3.809     0.2625     2.219     6.538

Concordance= 0.649  (se = 0.03 )
Likelihood ratio test= 26  on 1 df,   p=3e-07
Wald test            = 23.54  on 1 df,   p=1e-06
Score (logrank) test = 26.68  on 1 df,   p=2e-07
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 3.81 (2.22-6.54); p = 0"

#OS by ctDNA anytime post-surgery

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.anytime!="",]
circ_data$OS.months=circ_data$OS.months-2
circ_data <- circ_data[circ_data$OS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$OS.months, event = circ_data$OS.Event)~ctDNA.anytime, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$OS.months, event = circ_data$OS.Event) ~ 
    ctDNA.anytime, data = circ_data)

                        n events median 0.95LCL 0.95UCL
ctDNA.anytime=NEGATIVE 42     15     NA    48.4      NA
ctDNA.anytime=POSITIVE 47     41   27.6    21.3    35.3
event_summary <- circ_data %>%
  group_by(ctDNA.anytime) %>%
  summarise(
    Total = n(),
    Events = sum(OS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$OS.months, event = circ_data$OS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.anytime, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","red"), title="OS - ctDNA anytime post-surgery", ylab= "Overall Survival", xlab="Time (Months)", legend.labs=c("ctDNA Negative", "ctDNA Positive"), legend.title="")

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.anytime, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.anytime=NEGATIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     41       1    0.976  0.0235        0.843        0.997
   24     38       3    0.905  0.0453        0.766        0.963

                ctDNA.anytime=POSITIVE 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     41       6    0.872  0.0487        0.738        0.941
   24     26      15    0.553  0.0725        0.401        0.681
circ_data$ctDNA.anytime <- factor(circ_data$ctDNA.anytime, levels=c("NEGATIVE","POSITIVE"))
cox_fit <- coxph(surv_object ~ ctDNA.anytime, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.anytime, data = circ_data)

  n= 89, number of events= 56 

                        coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.anytimePOSITIVE 1.3272    3.7706   0.3039 4.367 1.26e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                      exp(coef) exp(-coef) lower .95 upper .95
ctDNA.anytimePOSITIVE     3.771     0.2652     2.078     6.841

Concordance= 0.648  (se = 0.033 )
Likelihood ratio test= 21.97  on 1 df,   p=3e-06
Wald test            = 19.07  on 1 df,   p=1e-05
Score (logrank) test = 21.89  on 1 df,   p=3e-06
cox_fit_summary <- summary(cox_fit)

# Extract values for HR, 95% CI, and p-value
HR <- cox_fit_summary$coefficients[2]
lower_CI <- cox_fit_summary$conf.int[3]
upper_CI <- cox_fit_summary$conf.int[4]
p_value <- cox_fit_summary$coefficients[5]
label_text <- paste0("HR = ", round(HR, 2), " (", round(lower_CI, 2), "-", round(upper_CI, 2), "); p = ", round(p_value, 3))
print(label_text)
[1] "HR = 3.77 (2.08-6.84); p = 0"

#Prognostic role of ctDNA Dynamics

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 48] <- 48
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

                                      n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=Converted Negative    12     10  13.57    8.94      NA
ctDNA.Dynamics=Converted Positive    11     11   5.43    4.60      NA
ctDNA.Dynamics=Persistently Negative 56     34  19.06   13.84      NA
ctDNA.Dynamics=Persistently Positive 10     10   5.10    2.40      NA
event_summary <- circ_data %>%
  group_by(ctDNA.Dynamics) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) 
KM_curve <- survfit(surv_object ~ ctDNA.Dynamics, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("blue","green","purple","red"), title="ctDNA Dynamics | Pre-treatment - On-treatment", ylab= "Disease Free Survival", xlab="Time from Surgery (Months)", legend.title="") 

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.Dynamics, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Dynamics=Converted Negative 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12      6       6    0.500   0.144        0.208        0.736
   24      5       1    0.417   0.142        0.152        0.665

                ctDNA.Dynamics=Converted Positive 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
     12.0000       2.0000       9.0000       0.1818       0.1163       0.0285       0.4417 

                ctDNA.Dynamics=Persistently Negative 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     36      19    0.656  0.0640        0.515        0.765
   24     26       9    0.489  0.0677        0.351        0.613

                ctDNA.Dynamics=Persistently Positive 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
    12.00000      1.00000      9.00000      0.10000      0.09487      0.00572      0.35813 
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("Persistently Negative","Converted Negative","Converted Positive", "Persistently Positive"))
cox_fit <- coxph(surv_object ~ ctDNA.Dynamics, data=circ_data)  
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Dynamics, data = circ_data)

  n= 89, number of events= 65 

                                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.DynamicsConverted Negative    0.3528    1.4230   0.3607 0.978    0.328    
ctDNA.DynamicsConverted Positive    1.7567    5.7935   0.3684 4.768 1.86e-06 ***
ctDNA.DynamicsPersistently Positive 1.9013    6.6944   0.3869 4.914 8.94e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.DynamicsConverted Negative        1.423     0.7027    0.7017     2.886
ctDNA.DynamicsConverted Positive        5.794     0.1726    2.8140    11.928
ctDNA.DynamicsPersistently Positive     6.694     0.1494    3.1358    14.291

Concordance= 0.659  (se = 0.031 )
Likelihood ratio test= 30.66  on 3 df,   p=1e-06
Wald test            = 35.98  on 3 df,   p=8e-08
Score (logrank) test = 44.86  on 3 df,   p=1e-09

#OS ctDNA Dynamics

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data$OS.months=circ_data$OS.months-2
circ_data <- circ_data[circ_data$OS.months>=0,]
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$OS.months, event = circ_data$OS.Event)~ctDNA.Dynamics, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$OS.months, event = circ_data$OS.Event) ~ 
    ctDNA.Dynamics, data = circ_data)

                                      n events median 0.95LCL 0.95UCL
ctDNA.Dynamics=Converted Negative    12      7   52.7   27.57      NA
ctDNA.Dynamics=Converted Positive    11     11   21.3   16.17      NA
ctDNA.Dynamics=Persistently Negative 56     28   48.4   29.28      NA
ctDNA.Dynamics=Persistently Positive 10     10   24.0    9.66      NA
event_summary <- circ_data %>%
  group_by(ctDNA.Dynamics) %>%
  summarise(
    Total = n(),
    Events = sum(OS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$OS.months, event = circ_data$OS.Event) 
KM_curve <- survfit(surv_object ~ ctDNA.Dynamics, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=6, palette=c("purple","green","blue","red"), title="MRD Dynamics | Pre-treatment - On-treatment", ylab= "Overall Survival", xlab="Time from Surgery (Months)", legend.title="") 

summary(KM_curve, times= c(12, 24))
Call: survfit(formula = surv_object ~ ctDNA.Dynamics, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

                ctDNA.Dynamics=Converted Negative 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     11       1    0.917  0.0798        0.539        0.988
   24      9       2    0.750  0.1250        0.408        0.912

                ctDNA.Dynamics=Converted Positive 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     10       1    0.909  0.0867        0.508        0.987
   24      5       5    0.455  0.1501        0.167        0.707

                ctDNA.Dynamics=Persistently Negative 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12     55       1    0.982  0.0177        0.880        0.997
   24     45      10    0.804  0.0531        0.673        0.886

                ctDNA.Dynamics=Persistently Positive 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
   12      6       4      0.6   0.155        0.253        0.827
   24      5       1      0.5   0.158        0.184        0.753
circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels=c("Persistently Negative","Converted Negative","Converted Positive", "Persistently Positive"))
cox_fit <- coxph(surv_object ~ ctDNA.Dynamics, data=circ_data)  
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.Dynamics, data = circ_data)

  n= 89, number of events= 56 

                                       coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.DynamicsConverted Negative    0.07171   1.07435  0.42352 0.169 0.865537    
ctDNA.DynamicsConverted Positive    1.10013   3.00455  0.36133 3.045 0.002329 ** 
ctDNA.DynamicsPersistently Positive 1.37436   3.95256  0.37891 3.627 0.000287 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                                    exp(coef) exp(-coef) lower .95 upper .95
ctDNA.DynamicsConverted Negative        1.074     0.9308    0.4684     2.464
ctDNA.DynamicsConverted Positive        3.005     0.3328    1.4799     6.100
ctDNA.DynamicsPersistently Positive     3.953     0.2530    1.8808     8.306

Concordance= 0.61  (se = 0.035 )
Likelihood ratio test= 16.29  on 3 df,   p=0.001
Wald test            = 18.53  on 3 df,   p=3e-04
Score (logrank) test = 21  on 3 df,   p=1e-04

#OP for pts converted positive during ACT

setwd("~/Downloads") 
clinstage<- read.csv("ASAN_Cholangio_OP.csv")
clinstage_df<- as.data.frame(clinstage)
clinstage_df <- clinstage_df[clinstage_df$ctDNA.Dynamics=="Converted Positive",]

##Overview plot - stratified by Stage
oplot_stratify <-swimmer_plot(df=clinstage_df,
                              id='PatientName',
                              end='fu.diff.months',
                              #name_fill='Arm',
                              col="gray",
                              alpha=0.75,
                              width=.01,
                              base_size = 14)
oplot_stratify <- oplot_stratify + theme(panel.border = element_blank())
oplot_stratify <- oplot_stratify + scale_y_continuous(breaks = seq(0, 108, by = 6))
oplot_stratify <- oplot_stratify + labs(x ="Patients" , y="Months from Surgery")
oplot_stratify


##plot events
oplot_ev3 <- oplot_stratify + swimmer_points(df_points=clinstage_df,
                                             id='PatientName',
                                             time='date.diff.months',
                                             name_shape ='Event_type',
                                             name_col = 'Event',
                                             size=3.5,fill='black',
                                             #col='darkgreen'
)
oplot_ev3
Warning: The shape palette can deal with a maximum of 6 discrete values because more than 6 becomes difficult to discriminate
ℹ you have requested 9 values. Consider specifying shapes manually if you need that many have them.
Warning: Removed 55 rows containing missing values or values outside the scale range (`geom_point()`).

#Shape customization to Event_type

oplot_ev3.1 <- oplot_ev3 + ggplot2::scale_shape_manual(name="Event_type",values=c(1,16,6,18,4, 5, 23, 7, 15),breaks=c('ctDNA_neg', 'ctDNA_pos', 'Imaging', 'Surgery', 'Death', "cea_neg", "cea_pos", "ca19_neg", "ca19_pos"))

oplot_ev3.1
Warning: Removed 11 rows containing missing values or values outside the scale range (`geom_point()`).

#plot treatment

oplot_ev4 <- oplot_ev3.1 + swimmer_lines(df_lines=clinstage_df,
                                         id='PatientName',
                                         start='Tx_start.months',
                                         end='Tx_end.months',
                                         name_col='Tx_type',
                                         size=3.5,
                                         name_alpha = 1.0)
oplot_ev4 <- oplot_ev4 + guides(linetype = guide_legend(override.aes = list(size = 5, color = "black")))
oplot_ev4  
Warning: Removed 11 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 133 rows containing missing values or values outside the scale range (`geom_segment()`).

#colour customization
# orange=ACT, Black=Death, Red=PD, ctDNA negative=white, ctDNA positive=black, Surgery=blue, TURBT=gray 
oplot_ev4.2 <- oplot_ev4 + ggplot2::scale_color_manual(name="Event",values=c( "orange", "purple", "blue", "black", "black", "red", "blue", "blue"))
oplot_ev4.2
Warning: Removed 11 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 133 rows containing missing values or values outside the scale range (`geom_segment()`).

#ctDNA clearance proportions by chemotherapy regimen

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- circ_data[circ_data$ctDNA.MRD=="POSITIVE",]

circ_data$ctDNA.Dynamics <- factor(circ_data$ctDNA.Dynamics, levels = c("Converted Negative", "Persistently Positive"), labels = c("Clearance", "No Clearance"))
circ_data$Chemo <- factor(circ_data$Chemo, levels = c("CAP", "GemCis"))
contingency_table <- table(circ_data$Chemo, circ_data$ctDNA.Dynamics)
chi_square_test <- chisq.test(contingency_table)
Warning in chisq.test(contingency_table) :
  Chi-squared approximation may be incorrect
print(chi_square_test)

    Pearson's Chi-squared test with Yates' continuity correction

data:  contingency_table
X-squared = 0.26481, df = 1, p-value = 0.6068
fisher_exact_test <- fisher.test(contingency_table)
print(fisher_exact_test)

    Fisher's Exact Test for Count Data

data:  contingency_table
p-value = 0.4149
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
  0.3023403 20.3968347
sample estimates:
odds ratio 
   2.24368 
print(contingency_table)
        
         Clearance No Clearance
  CAP            6            3
  GemCis         6            7
table_df <- as.data.frame(contingency_table)
table_df$Total <- ave(table_df$Freq, table_df$Var1, FUN = sum)
table_df$Percentage <- table_df$Freq / table_df$Total
table_df$MiddlePercentage <- table_df$Percentage / 2
ggplot(table_df, aes(x = Var1, y = Percentage, fill = Var2)) +
  geom_bar(stat = "identity") +
  geom_text(aes(y = MiddlePercentage, label = Freq), position = "stack", color = "black", vjust = 1.5, size = 7) +
  theme_minimal() +
  labs(title = "ctDNA clearance by Regimen", 
       x = "Regimen", 
       y = "Patients (%)", 
       fill = "ctDNA Clearance",
       caption = paste("Fisher's exact test p-value: ", format.pval(fisher_exact_test$p.value))) +
  scale_y_continuous(labels = scales::percent_format()) +
  scale_fill_manual(values = c("Clearance" = "blue", "No Clearance" = "red")) + # define custom colors
  theme(axis.text.x = element_text(angle = 0, hjust = 1.5, size = 14), # increase x-axis text size
        axis.text.y = element_text(size = 14, color = "black"), # increase y-axis text size
        axis.title.x = element_text(size = 14, color = "black"), # increase x-axis label size
        axis.title.y = element_text(size = 14, color = "black"), # increase y-axis label size
        legend.text = element_text(size = 12, color = "black"))  # increase Progression label size

#Prognostic role of ctDNA C5D1 on Chemotherapy - 4 groups

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60


circ_data$ctDNA.C5D1.Chemo <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C5D1.Chemo = case_when(
    Chemo == "CAP" & ctDNA.C5D1 == "NEGATIVE" ~ 1,
    Chemo == "CAP" & ctDNA.C5D1 == "POSITIVE" ~ 2,
    Chemo == "GemCis" & ctDNA.C5D1 == "NEGATIVE" ~ 3,
    Chemo == "GemCis" & ctDNA.C5D1 == "POSITIVE" ~ 4
  ))
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.C5D1.Chemo, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.C5D1.Chemo, data = circ_data)

   1 observation deleted due to missingness 
                    n events median 0.95LCL 0.95UCL
ctDNA.C5D1.Chemo=1 36     24  15.58   11.57      NA
ctDNA.C5D1.Chemo=2  8      8   3.95    2.27      NA
ctDNA.C5D1.Chemo=3 35     24  16.79   11.96    38.7
ctDNA.C5D1.Chemo=4  9      9   4.83    3.59      NA
event_summary <- circ_data %>%
  group_by(ctDNA.C5D1.Chemo) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C5D1.Chemo, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA C5D1 & Chemotherapy Regimen", ylab= "Disease Free Survival", xlab="Months from surgery", legend.labs=c("CAP & ctDNA(-)", "CAP & ctDNA(+)","GemCis & ctDNA(-)", "GemCis & ctDNA(+)"), legend.title="")

summary(KM_curve, times= c(0, 12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C5D1.Chemo, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

1 observation deleted due to missingness 
                ctDNA.C5D1.Chemo=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     36       0    1.000  0.0000        1.000        1.000
   12     21      14    0.602  0.0827        0.422        0.741
   24     14       7    0.401  0.0829        0.241        0.556

                ctDNA.C5D1.Chemo=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            8            0            1            0            1            1 

                ctDNA.C5D1.Chemo=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     35       0    1.000  0.0000        1.000        1.000
   12     22      13    0.629  0.0817        0.448        0.765
   24     16       5    0.481  0.0851        0.309        0.634

                ctDNA.C5D1.Chemo=4 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0    1.000   0.000      1.00000        1.000
   12      1       8    0.111   0.105      0.00613        0.388
circ_data$ctDNA.C5D1.Chemo <- factor(circ_data$ctDNA.C5D1.Chemo, levels=c("1","2","3","4"))
cox_fit <- coxph(surv_object ~ ctDNA.C5D1.Chemo, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C5D1.Chemo, data = circ_data)

  n= 88, number of events= 65 
   (1 observation deleted due to missingness)

                      coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.C5D1.Chemo2  2.34287  10.41111  0.45548 5.144 2.69e-07 ***
ctDNA.C5D1.Chemo3  0.00918   1.00922  0.28914 0.032    0.975    
ctDNA.C5D1.Chemo4  1.87019   6.48950  0.41611 4.494 6.97e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C5D1.Chemo2    10.411    0.09605    4.2637    25.422
ctDNA.C5D1.Chemo3     1.009    0.99086    0.5726     1.779
ctDNA.C5D1.Chemo4     6.490    0.15409    2.8709    14.669

Concordance= 0.639  (se = 0.035 )
Likelihood ratio test= 32.54  on 3 df,   p=4e-07
Wald test            = 40.73  on 3 df,   p=7e-09
Score (logrank) test = 55.87  on 3 df,   p=4e-12
cox_fit_summary <- summary(cox_fit)

#Prognostic role of ctDNA C8D1 on Chemotherapy - 4 groups

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C8D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60


circ_data$ctDNA.C8D1.Chemo <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C8D1.Chemo = case_when(
    Chemo == "CAP" & ctDNA.C8D1 == "NEGATIVE" ~ 1,
    Chemo == "CAP" & ctDNA.C8D1 == "POSITIVE" ~ 2,
    Chemo == "GemCis" & ctDNA.C8D1 == "NEGATIVE" ~ 3,
    Chemo == "GemCis" & ctDNA.C8D1 == "POSITIVE" ~ 4
  ))
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.C8D1.Chemo, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.C8D1.Chemo, data = circ_data)

   12 observations deleted due to missingness 
                    n events median 0.95LCL 0.95UCL
ctDNA.C8D1.Chemo=1 31     20  15.84   11.57      NA
ctDNA.C8D1.Chemo=2  6      6   7.86    5.43      NA
ctDNA.C8D1.Chemo=3 31     20  26.98   13.51      NA
ctDNA.C8D1.Chemo=4  9      9   6.44    4.83      NA
event_summary <- circ_data %>%
  group_by(ctDNA.C8D1.Chemo) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C8D1.Chemo, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA C8D1 & Chemotherapy Regimen", ylab= "Disease Free Survival", xlab="Months from surgery", legend.labs=c("CAP & ctDNA(-)", "CAP & ctDNA(+)","GemCis & ctDNA(-)", "GemCis & ctDNA(+)"), legend.title="")

summary(KM_curve, times= c(0, 12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C8D1.Chemo, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

12 observations deleted due to missingness 
                ctDNA.C8D1.Chemo=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000  0.0000        1.000        1.000
   12     19      12    0.613  0.0875        0.420        0.758
   24     13       6    0.419  0.0886        0.247        0.583

                ctDNA.C8D1.Chemo=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      6       0    1.000   0.000      1.00000        1.000
   12      1       5    0.167   0.152      0.00772        0.517

                ctDNA.C8D1.Chemo=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000   0.000        1.000        1.000
   12     21      10    0.677   0.084        0.484        0.812
   24     16       4    0.545   0.090        0.355        0.700

                ctDNA.C8D1.Chemo=4 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0    1.000   0.000       1.0000        1.000
   12      2       7    0.222   0.139       0.0337        0.513
circ_data$ctDNA.C8D1.Chemo <- factor(circ_data$ctDNA.C8D1.Chemo, levels=c("1","2","3","4"))
cox_fit <- coxph(surv_object ~ ctDNA.C8D1.Chemo, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C8D1.Chemo, data = circ_data)

  n= 77, number of events= 55 
   (12 observations deleted due to missingness)

                      coef exp(coef) se(coef)      z Pr(>|z|)    
ctDNA.C8D1.Chemo2  1.59481   4.92738  0.48599  3.282  0.00103 ** 
ctDNA.C8D1.Chemo3 -0.06279   0.93914  0.31645 -0.198  0.84271    
ctDNA.C8D1.Chemo4  1.64389   5.17525  0.41910  3.922 8.76e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                  exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C8D1.Chemo2    4.9274     0.2029    1.9008    12.773
ctDNA.C8D1.Chemo3    0.9391     1.0648    0.5051     1.746
ctDNA.C8D1.Chemo4    5.1753     0.1932    2.2761    11.767

Concordance= 0.638  (se = 0.037 )
Likelihood ratio test= 20.58  on 3 df,   p=1e-04
Wald test            = 25.53  on 3 df,   p=1e-05
Score (logrank) test = 31.47  on 3 df,   p=7e-07
cox_fit_summary <- summary(cox_fit)

#Prognostic role of ctDNA C5D1 on Primary Site - 4 groups

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C5D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60


circ_data$ctDNA.C5D1.PrimSite <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C5D1.PrimSite = case_when(
    PrimSite == "dCCA" & ctDNA.C5D1 == "NEGATIVE" ~ 1,
    PrimSite == "dCCA" & ctDNA.C5D1 == "POSITIVE" ~ 2,
    PrimSite == "pCCA" & ctDNA.C5D1 == "NEGATIVE" ~ 3,
    PrimSite == "pCCA" & ctDNA.C5D1 == "POSITIVE" ~ 4
  ))
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.C5D1.PrimSite, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.C5D1.PrimSite, data = circ_data)

   1 observation deleted due to missingness 
                       n events median 0.95LCL 0.95UCL
ctDNA.C5D1.PrimSite=1 37     20  16.79   11.96      NA
ctDNA.C5D1.PrimSite=2  8      8   3.88    2.27      NA
ctDNA.C5D1.PrimSite=3 34     28  15.71   11.63    27.3
ctDNA.C5D1.PrimSite=4  9      9   4.80    3.59      NA
event_summary <- circ_data %>%
  group_by(ctDNA.C5D1.PrimSite) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C5D1.PrimSite, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA C5D1 & Primary Site", ylab= "Disease Free Survival", xlab="Months from surgery", legend.labs=c("dCCA & ctDNA(-)", "dCCA & ctDNA(+)","pCCA & ctDNA(-)", "pCCA & ctDNA(+)"), legend.title="")

summary(KM_curve, times= c(0, 12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C5D1.PrimSite, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

1 observation deleted due to missingness 
                ctDNA.C5D1.PrimSite=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     37       0    1.000  0.0000        1.000        1.000
   12     22      14    0.613  0.0811        0.435        0.749
   24     17       4    0.498  0.0838        0.327        0.648

                ctDNA.C5D1.PrimSite=2 
        time       n.risk      n.event     survival      std.err lower 95% CI upper 95% CI 
           0            8            0            1            0            1            1 

                ctDNA.C5D1.PrimSite=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     34       0    1.000  0.0000        1.000        1.000
   12     21      13    0.618  0.0833        0.434        0.757
   24     13       8    0.382  0.0833        0.223        0.540

                ctDNA.C5D1.PrimSite=4 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      9       0    1.000   0.000      1.00000        1.000
   12      1       8    0.111   0.105      0.00613        0.388
circ_data$ctDNA.C5D1.PrimSite <- factor(circ_data$ctDNA.C5D1.PrimSite, levels=c("1","2","3","4"))
cox_fit <- coxph(surv_object ~ ctDNA.C5D1.PrimSite, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C5D1.PrimSite, data = circ_data)

  n= 88, number of events= 65 
   (1 observation deleted due to missingness)

                        coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.C5D1.PrimSite2  2.4864   12.0174   0.4637 5.362 8.24e-08 ***
ctDNA.C5D1.PrimSite3  0.5269    1.6937   0.2948 1.787   0.0739 .  
ctDNA.C5D1.PrimSite4  2.2230    9.2352   0.4307 5.162 2.45e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                     exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C5D1.PrimSite2    12.017    0.08321    4.8428    29.821
ctDNA.C5D1.PrimSite3     1.694    0.59042    0.9503     3.019
ctDNA.C5D1.PrimSite4     9.235    0.10828    3.9706    21.480

Concordance= 0.665  (se = 0.035 )
Likelihood ratio test= 35.17  on 3 df,   p=1e-07
Wald test            = 41.85  on 3 df,   p=4e-09
Score (logrank) test = 56.32  on 3 df,   p=4e-12
cox_fit_summary <- summary(cox_fit)

#Prognostic role of ctDNA C8D1 on Primary Site - 4 groups

rm(list=ls())
setwd("~/Downloads") 
circ_data <- read.csv("ASAN_ClinicalData_GL_082023.csv")
circ_data <- subset(circ_data, !is.na(ctDNA.C8D1))
circ_data$RFS.months=circ_data$RFS.months-2
circ_data <- circ_data[circ_data$RFS.months>=0,]
circ_data$RFS.months[circ_data$RFS.months > 60] <- 60


circ_data$ctDNA.C8D1.PrimSite <- NA #first we create the variable for the ctDNA & NAC combination, and we assign values
circ_data <- circ_data %>%
  mutate(ctDNA.C8D1.PrimSite = case_when(
    PrimSite == "dCCA" & ctDNA.C8D1 == "NEGATIVE" ~ 1,
    PrimSite == "dCCA" & ctDNA.C8D1 == "POSITIVE" ~ 2,
    PrimSite == "pCCA" & ctDNA.C8D1 == "NEGATIVE" ~ 3,
    PrimSite == "pCCA" & ctDNA.C8D1 == "POSITIVE" ~ 4
  ))
circ_datadf <- as.data.frame(circ_data)

survfit(Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)~ctDNA.C8D1.PrimSite, data = circ_data)
Call: survfit(formula = Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event) ~ 
    ctDNA.C8D1.PrimSite, data = circ_data)

   12 observations deleted due to missingness 
                       n events median 0.95LCL 0.95UCL
ctDNA.C8D1.PrimSite=1 31     15  38.71   13.51      NA
ctDNA.C8D1.PrimSite=2  8      8   7.50    6.44      NA
ctDNA.C8D1.PrimSite=3 31     25  15.84   10.98    27.6
ctDNA.C8D1.PrimSite=4  7      7   5.43    4.60      NA
event_summary <- circ_data %>%
  group_by(ctDNA.C8D1.PrimSite) %>%
  summarise(
    Total = n(),
    Events = sum(RFS.Event),
    Fraction = Events / n(),
    Percentage = (Events / n()) * 100
  )
print(event_summary)
surv_object <-Surv(time = circ_data$RFS.months, event = circ_data$RFS.Event)
KM_curve <- survfit(surv_object ~ ctDNA.C8D1.PrimSite, data = circ_data,conf.int=0.95,conf.type="log-log") 
ggsurvplot(KM_curve, data = circ_data, pval = FALSE, conf.int = FALSE, risk.table = TRUE, break.time.by=12, palette=c("blue","green","purple", "red"), title="DFS - ctDNA C8D1 & Primary Site", ylab= "Disease Free Survival", xlab="Months from surgery", legend.labs=c("dCCA & ctDNA(-)", "dCCA & ctDNA(+)","pCCA & ctDNA(-)", "pCCA & ctDNA(+)"), legend.title="")

summary(KM_curve, times= c(0, 12, 24))
Call: survfit(formula = surv_object ~ ctDNA.C8D1.PrimSite, data = circ_data, 
    conf.int = 0.95, conf.type = "log-log")

12 observations deleted due to missingness 
                ctDNA.C8D1.PrimSite=1 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000   0.000        1.000        1.000
   12     21      10    0.677   0.084        0.484        0.812
   24     17       3    0.579   0.089        0.387        0.730

                ctDNA.C8D1.PrimSite=2 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      8       0    1.000   0.000      1.00000        1.000
   12      1       7    0.125   0.117      0.00659        0.423

                ctDNA.C8D1.PrimSite=3 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0     31       0    1.000  0.0000         1.00        1.000
   12     19      12    0.613  0.0875         0.42        0.758
   24     12       7    0.387  0.0875         0.22        0.551

                ctDNA.C8D1.PrimSite=4 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    0      7       0    1.000   0.000       1.0000        1.000
   12      2       5    0.286   0.171       0.0411        0.612
circ_data$ctDNA.C8D1.PrimSite <- factor(circ_data$ctDNA.C8D1.PrimSite, levels=c("1","2","3","4"))
cox_fit <- coxph(surv_object ~ ctDNA.C8D1.PrimSite, data=circ_data) 
ggforest(cox_fit,data = circ_data) 

summary(cox_fit)
Call:
coxph(formula = surv_object ~ ctDNA.C8D1.PrimSite, data = circ_data)

  n= 77, number of events= 55 
   (12 observations deleted due to missingness)

                       coef exp(coef) se(coef)     z Pr(>|z|)    
ctDNA.C8D1.PrimSite2 2.1501    8.5860   0.4665 4.609 4.05e-06 ***
ctDNA.C8D1.PrimSite3 0.7532    2.1239   0.3301 2.282   0.0225 *  
ctDNA.C8D1.PrimSite4 2.0206    7.5431   0.4794 4.215 2.50e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

                     exp(coef) exp(-coef) lower .95 upper .95
ctDNA.C8D1.PrimSite2     8.586     0.1165     3.441    21.424
ctDNA.C8D1.PrimSite3     2.124     0.4708     1.112     4.056
ctDNA.C8D1.PrimSite4     7.543     0.1326     2.948    19.303

Concordance= 0.671  (se = 0.036 )
Likelihood ratio test= 26.02  on 3 df,   p=9e-06
Wald test            = 28.78  on 3 df,   p=2e-06
Score (logrank) test = 35.81  on 3 df,   p=8e-08
cox_fit_summary <- summary(cox_fit)
LS0tCnRpdGxlOiAiQVNBTiBDaG9sYW5naW9fR0xfRmluYWwgYW5hbHlzaXMgMDkyMDI0IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmxpYnJhcnkoc3dpbXBsb3QpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShndGFibGUpCmxpYnJhcnkocmVhZHIpIApsaWJyYXJ5KG1vc2FpYykKbGlicmFyeShkcGx5cikgCmxpYnJhcnkoc3Vydml2YWwpIApsaWJyYXJ5KHN1cnZtaW5lcikgCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoY294cGhmKQpsaWJyYXJ5KGdndGhlbWVzKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShndHN1bW1hcnkpCmxpYnJhcnkoZmxleHRhYmxlKQpsaWJyYXJ5KHBhcmFtZXRlcnMpCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQpsaWJyYXJ5KHJtcykKCiNjdEROQSBwb3NpdGl2aXR5IGJ5IHN0YWdlIGFuZCB3aW5kb3cKYGBge3J9CiNjdEROQSBhdCBNUkQKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5NUkQhPSIiLF0KY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsIGN0RE5BLk1SRCAlaW4lIGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIikpCmNpcmNfZGF0YSRTdGFnZSA8LSBmYWN0b3IoY2lyY19kYXRhJFN0YWdlLCBsZXZlbHM9YygiSUkiLCJJSUkiLCJJViIpKQpwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5NUkQgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5NUkQsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPWxlbmd0aCkKY29tYmluZWRfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gdG90YWxfY291bnRzX2J5X3N0YWdlJEdyb3VwLjEsCiAgVG90YWxfQ291bnQgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCwKICBQb3NpdGl2ZV9Db3VudCA9IHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4LAogIFJhdGUgPSAocG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHggLyB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCikKY29tYmluZWRfZGF0YSRSYXRlIDwtIHNwcmludGYoIiUuMmYlJSIsIGNvbWJpbmVkX2RhdGEkUmF0ZSkKb3ZlcmFsbF90b3RhbF9jb3VudCA8LSBucm93KGNpcmNfZGF0YSkKb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCA8LSBucm93KGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEID09ICJQT1NJVElWRSIsXSkKb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUgPC0gKG92ZXJhbGxfcG9zaXRpdmVfY291bnQgLyBvdmVyYWxsX3RvdGFsX2NvdW50KSAqIDEwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2UKb3ZlcmFsbF9yb3cgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9ICJPdmVyYWxsIiwKICBUb3RhbF9Db3VudCA9IG92ZXJhbGxfdG90YWxfY291bnQsCiAgUG9zaXRpdmVfQ291bnQgPSBvdmVyYWxsX3Bvc2l0aXZlX2NvdW50LAogIFJhdGUgPSBzcHJpbnRmKCIlLjJmJSUiLCBvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSkKKQpjb21iaW5lZF9kYXRhIDwtIHJiaW5kKGNvbWJpbmVkX2RhdGEsIG92ZXJhbGxfcm93KQpwcmludChjb21iaW5lZF9kYXRhKQoKI2N0RE5BIEM1RDEKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKQpjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5DNUQxIT0iIixdCmNpcmNfZGF0YSRjdEROQS5DNUQxIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQzVEMSwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsIGN0RE5BLkM1RDEgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIklJIiwiSUlJIiwiSVYiKSkKcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuQzVEMSA9PSAiUE9TSVRJVkUiLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1zdW0pCnRvdGFsX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLkM1RDEsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPWxlbmd0aCkKY29tYmluZWRfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gdG90YWxfY291bnRzX2J5X3N0YWdlJEdyb3VwLjEsCiAgVG90YWxfQ291bnQgPSB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCwKICBQb3NpdGl2ZV9Db3VudCA9IHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4LAogIFJhdGUgPSAocG9zaXRpdmVfY291bnRzX2J5X3N0YWdlJHggLyB0b3RhbF9jb3VudHNfYnlfc3RhZ2UkeCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCikKY29tYmluZWRfZGF0YSRSYXRlIDwtIHNwcmludGYoIiUuMmYlJSIsIGNvbWJpbmVkX2RhdGEkUmF0ZSkKb3ZlcmFsbF90b3RhbF9jb3VudCA8LSBucm93KGNpcmNfZGF0YSkKb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCA8LSBucm93KGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzVEMSA9PSAiUE9TSVRJVkUiLF0pCm92ZXJhbGxfcG9zaXRpdml0eV9yYXRlIDwtIChvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IC8gb3ZlcmFsbF90b3RhbF9jb3VudCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCm92ZXJhbGxfcm93IDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSAiT3ZlcmFsbCIsCiAgVG90YWxfQ291bnQgPSBvdmVyYWxsX3RvdGFsX2NvdW50LAogIFBvc2l0aXZlX0NvdW50ID0gb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCwKICBSYXRlID0gc3ByaW50ZigiJS4yZiUlIiwgb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUpCikKY29tYmluZWRfZGF0YSA8LSByYmluZChjb21iaW5lZF9kYXRhLCBvdmVyYWxsX3JvdykKcHJpbnQoY29tYmluZWRfZGF0YSkKCiNjdEROQSBDOEQxCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzhEMSE9IiIsXQpjaXJjX2RhdGEkY3RETkEuQzhEMSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkM4RDEsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCBjdEROQS5DOEQxICVpbiUgYygiTkVHQVRJVkUiLCAiUE9TSVRJVkUiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscz1jKCJJSSIsIklJSSIsIklWIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLkM4RDEgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5DOEQxLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkM4RDEgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCgojY3RETkEgRU9UCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuRU9UIT0iIixdCmNpcmNfZGF0YSRjdEROQS5FT1QgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5FT1QsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCBjdEROQS5FT1QgJWluJSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzPWMoIklJIiwiSUlJIiwiSVYiKSkKcG9zaXRpdmVfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuRU9UID09ICJQT1NJVElWRSIsIGJ5PWxpc3QoY2lyY19kYXRhJFN0YWdlKSwgRlVOPXN1bSkKdG90YWxfY291bnRzX2J5X3N0YWdlIDwtIGFnZ3JlZ2F0ZShjaXJjX2RhdGEkY3RETkEuRU9ULCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkVPVCA9PSAiUE9TSVRJVkUiLF0pCm92ZXJhbGxfcG9zaXRpdml0eV9yYXRlIDwtIChvdmVyYWxsX3Bvc2l0aXZlX2NvdW50IC8gb3ZlcmFsbF90b3RhbF9jb3VudCkgKiAxMDAgICMgQ29udmVydCB0byBwZXJjZW50YWdlCm92ZXJhbGxfcm93IDwtIGRhdGEuZnJhbWUoCiAgU3RhZ2UgPSAiT3ZlcmFsbCIsCiAgVG90YWxfQ291bnQgPSBvdmVyYWxsX3RvdGFsX2NvdW50LAogIFBvc2l0aXZlX0NvdW50ID0gb3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCwKICBSYXRlID0gc3ByaW50ZigiJS4yZiUlIiwgb3ZlcmFsbF9wb3NpdGl2aXR5X3JhdGUpCikKY29tYmluZWRfZGF0YSA8LSByYmluZChjb21iaW5lZF9kYXRhLCBvdmVyYWxsX3JvdykKcHJpbnQoY29tYmluZWRfZGF0YSkKCiNjdEROQSBhbnl0aW1lCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuYW55dGltZSE9IiIsXQpjaXJjX2RhdGEkY3RETkEuYW55dGltZSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLmFueXRpbWUsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCBjdEROQS5hbnl0aW1lICVpbiUgYygiTkVHQVRJVkUiLCAiUE9TSVRJVkUiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscz1jKCJJSSIsIklJSSIsIklWIikpCnBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSA8LSBhZ2dyZWdhdGUoY2lyY19kYXRhJGN0RE5BLmFueXRpbWUgPT0gIlBPU0lUSVZFIiwgYnk9bGlzdChjaXJjX2RhdGEkU3RhZ2UpLCBGVU49c3VtKQp0b3RhbF9jb3VudHNfYnlfc3RhZ2UgPC0gYWdncmVnYXRlKGNpcmNfZGF0YSRjdEROQS5hbnl0aW1lLCBieT1saXN0KGNpcmNfZGF0YSRTdGFnZSksIEZVTj1sZW5ndGgpCmNvbWJpbmVkX2RhdGEgPC0gZGF0YS5mcmFtZSgKICBTdGFnZSA9IHRvdGFsX2NvdW50c19ieV9zdGFnZSRHcm91cC4xLAogIFRvdGFsX0NvdW50ID0gdG90YWxfY291bnRzX2J5X3N0YWdlJHgsCiAgUG9zaXRpdmVfQ291bnQgPSBwb3NpdGl2ZV9jb3VudHNfYnlfc3RhZ2UkeCwKICBSYXRlID0gKHBvc2l0aXZlX2NvdW50c19ieV9zdGFnZSR4IC8gdG90YWxfY291bnRzX2J5X3N0YWdlJHgpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQopCmNvbWJpbmVkX2RhdGEkUmF0ZSA8LSBzcHJpbnRmKCIlLjJmJSUiLCBjb21iaW5lZF9kYXRhJFJhdGUpCm92ZXJhbGxfdG90YWxfY291bnQgPC0gbnJvdyhjaXJjX2RhdGEpCm92ZXJhbGxfcG9zaXRpdmVfY291bnQgPC0gbnJvdyhjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLmFueXRpbWUgPT0gIlBPU0lUSVZFIixdKQpvdmVyYWxsX3Bvc2l0aXZpdHlfcmF0ZSA8LSAob3ZlcmFsbF9wb3NpdGl2ZV9jb3VudCAvIG92ZXJhbGxfdG90YWxfY291bnQpICogMTAwICAjIENvbnZlcnQgdG8gcGVyY2VudGFnZQpvdmVyYWxsX3JvdyA8LSBkYXRhLmZyYW1lKAogIFN0YWdlID0gIk92ZXJhbGwiLAogIFRvdGFsX0NvdW50ID0gb3ZlcmFsbF90b3RhbF9jb3VudCwKICBQb3NpdGl2ZV9Db3VudCA9IG92ZXJhbGxfcG9zaXRpdmVfY291bnQsCiAgUmF0ZSA9IHNwcmludGYoIiUuMmYlJSIsIG92ZXJhbGxfcG9zaXRpdml0eV9yYXRlKQopCmNvbWJpbmVkX2RhdGEgPC0gcmJpbmQoY29tYmluZWRfZGF0YSwgb3ZlcmFsbF9yb3cpCnByaW50KGNvbWJpbmVkX2RhdGEpCmBgYAoKCiNIZWF0bWFwIGZvciBjbGluaWNvcGF0aG9sb2dpYyBmYWN0b3JzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUgYXJyYW5nZShTdGFnZSkKY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpoYSA8LSBIZWF0bWFwQW5ub3RhdGlvbigKICBTdGFnZSA9IGNpcmNfZGF0YSRTdGFnZSwKICBTZXggPSBjaXJjX2RhdGEkU2V4LAogIFByaW1TaXRlID0gY2lyY19kYXRhJFByaW1TaXRlLAogIHBUID0gY2lyY19kYXRhJHBULAogIFBhdGhvbG9neSA9IGNpcmNfZGF0YSRQYXRob2xvZ3ksCiAgQ2hlbW8gPSBjaXJjX2RhdGEkQ2hlbW8sCiAgY3RETkEuTVJEID0gY2lyY19kYXRhJGN0RE5BLk1SRCwKICBjdEROQS5DNUQxID0gY2lyY19kYXRhJGN0RE5BLkM1RDEsCiAgY3RETkEuQzhEMSA9IGNpcmNfZGF0YSRjdEROQS5DOEQxLAogIGN0RE5BLkVPVCA9IGNpcmNfZGF0YSRjdEROQS5FT1QsCiAgY3RETkEuYW55dGltZSA9IGNpcmNfZGF0YSRjdEROQS5hbnl0aW1lLAogIFJlY1N0YXR1cyA9IGNpcmNfZGF0YSRSZWNTdGF0dXMsCiAgVml0YWxTdGF0dXMgPSBjaXJjX2RhdGEkVml0YWxTdGF0dXMsCiAgCiAgICBjb2wgPSBsaXN0KFN0YWdlID0gYygiSUkiID0gInNlYWdyZWVuMiIsICJJSUkiID0gIm9yYW5nZSIsICJJViIgPSAicHVycGxlIiksCiAgICBTZXggPSBjKCJGZW1hbGUiID0gImdvbGRlbnJvZCIgLCAiTWFsZSIgPSAiYmx1ZTQiKSwKICAgIFByaW1TaXRlID0gYygicENDQSIgPSAiZGFya2dyZWVuIiwgImRDQ0EiID0iIzAwOEJDRSIpLAogICAgcFQgPSBjKCJUMSIgPSAibGlnaHRibHVlIiwgIlQyIiA9Im9yYW5nZSIsICJUMyIgPSAiYnJvd24iICksCiAgICBQYXRob2xvZ3kgPSBjKCJHMSIgPSAieWVsbG93MyIsICJHMiIgPSJkYXJrZ3JlZW4iLCAiRzMiID0gImJyb3duMiIpLAogICAgQ2hlbW8gPSBjKCJDQVAiID0gImxpZ2h0Ymx1ZSIsICJHZW1DaXMiID0gIm9yYW5nZTIiKSwKICAgIGN0RE5BLk1SRCA9IGMoIlBPU0lUSVZFIiA9ICJyZWQzIiwgIk5FR0FUSVZFIiA9ImJsdWUiKSwKICAgIGN0RE5BLkM1RDEgPSBjKCJQT1NJVElWRSIgPSAicmVkMyIsICJORUdBVElWRSIgPSJibHVlIiksCiAgICBjdEROQS5DOEQxID0gYygiUE9TSVRJVkUiID0gInJlZDMiLCAiTkVHQVRJVkUiID0iYmx1ZSIpLAogICAgY3RETkEuRU9UID0gYygiUE9TSVRJVkUiID0gInJlZDMiLCAiTkVHQVRJVkUiID0iYmx1ZSIpLAogICAgY3RETkEuYW55dGltZSA9IGMoIlBPU0lUSVZFIiA9ICJyZWQzIiwgIk5FR0FUSVZFIiA9ImJsdWUiKSwKICAgIFJGUy5FdmVudCA9IGMoIlRSVUUiID0gInJlZDMiLCAiRkFMU0UiID0iYmx1ZSIpLAogICAgT1MuRXZlbnQgPSBjKCJUUlVFIiA9ICJibGFjayIsICJGQUxTRSIgPSJncmV5IikKKQopCmh0IDwtIEhlYXRtYXAobWF0cml4KG5yb3cgPSAwLCBuY29sID0gbGVuZ3RoKGNpcmNfZGF0YSRTdGFnZSkpLHNob3dfcm93X25hbWVzID0gRkFMU0UsY2x1c3Rlcl9yb3dzID0gRixjbHVzdGVyX2NvbHVtbnMgPSBGQUxTRSwgdG9wX2Fubm90YXRpb24gPSBoYSkKcGRmKCJoZWF0bWFwLnBkZiIsd2lkdGggPSA3LCBoZWlnaHQgPSA3KQpkcmF3KGh0LCBhbm5vdGF0aW9uX2xlZ2VuZF9zaWRlID0gImJvdHRvbSIpCmRldi5vZmYoKQpgYGAKCgojUHJvZ25vc3RpYyByb2xlIG9mIGN0RE5BIGF0IHRoZSBNUkQgdGltZSBwb2ludApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhJFJGUy5tb250aHM9Y2lyY19kYXRhJFJGUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRSRlMubW9udGhzPj0wLF0KY2lyY19kYXRhJFJGUy5tb250aHNbY2lyY19kYXRhJFJGUy5tb250aHMgPiA2MF0gPC0gNjAKY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpfmN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSkKZXZlbnRfc3VtbWFyeSA8LSBjaXJjX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY3RETkEuTVJEKSAlPiUKICBzdW1tYXJpc2UoCiAgICBUb3RhbCA9IG4oKSwKICAgIEV2ZW50cyA9IHN1bShSRlMuRXZlbnQpLAogICAgRnJhY3Rpb24gPSBFdmVudHMgLyBuKCksCiAgICBQZXJjZW50YWdlID0gKEV2ZW50cyAvIG4oKSkgKiAxMDAKICApCnByaW50KGV2ZW50X3N1bW1hcnkpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IkRGUyAtIGN0RE5BIE1SRCB0aW1lcG9pbnQiLCB5bGFiPSAiRGlzZWFzZSBGcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMTIsIDI0KSkKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLk1SRCwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKI09TIGJ5IGN0RE5BIGF0IHRoZSBNUkQgdGltZSBwb2ludApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhJE9TLm1vbnRocz1jaXJjX2RhdGEkT1MubW9udGhzLTIKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkT1MubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRPUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5NUkQsIGRhdGEgPSBjaXJjX2RhdGEpCmV2ZW50X3N1bW1hcnkgPC0gY2lyY19kYXRhICU+JQogIGdyb3VwX2J5KGN0RE5BLk1SRCkgJT4lCiAgc3VtbWFyaXNlKAogICAgVG90YWwgPSBuKCksCiAgICBFdmVudHMgPSBzdW0oT1MuRXZlbnQpLAogICAgRnJhY3Rpb24gPSBFdmVudHMgLyBuKCksCiAgICBQZXJjZW50YWdlID0gKEV2ZW50cyAvIG4oKSkgKiAxMDAKICApCnByaW50KGV2ZW50X3N1bW1hcnkpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJE9TLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIE1SRCB0aW1lcG9pbnQiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDEyLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5NUkQgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5NUkQsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5NUkQsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCiNBc3NvY2lhdGlvbiBvZiBjdEROQSBNUkQgTVRNIGxldmVscyB3aXRoIGNsaW5pY29wYXRob2xvZ2ljYWwgZmFjdG9ycwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKCnRhbGx5KH5wTiwgZGF0YT1jaXJjX2RhdGEsIG1hcmdpbnMgPSBUUlVFKQpjaXJjX2RhdGEkcE4gPC0gZmFjdG9yKGNpcmNfZGF0YSRwTiwgbGV2ZWxzID0gYygiTjEiLCJOMiIpLCBsYWJlbHMgPSBjKCJwTjEgKG49NjkpIiwicE4yIChuPTIwKSIpKQpib3hwbG90KGN0RE5BLk1SRC5NVE1+cE4sIGRhdGE9Y2lyY19kYXRhLCBtYWluPSJjdEROQSBNUkQgTVRNIC0gcE4iLCB4bGFiPSJwTiIsIHlsYWI9Ik1UTS9tTCIsIGNvbD0id2hpdGUiLGJvcmRlcj0iYmxhY2siLCB5bGltPWMoMCwgMTApKQptMTwtd2lsY294LnRlc3QoY3RETkEuTVJELk1UTSB+IHBOLCBkYXRhPWNpcmNfZGF0YSwgbmEucm09VFJVRSwgZXhhY3Q9RkFMU0UsIGNvbmYuaW50PVRSVUUpCnByaW50KG0xKQoKdGFsbHkoflJlc01hcmcsIGRhdGE9Y2lyY19kYXRhLCBtYXJnaW5zID0gVFJVRSkKY2lyY19kYXRhJFJlc01hcmcgPC0gZmFjdG9yKGNpcmNfZGF0YSRSZXNNYXJnLCBsZXZlbHMgPSBjKCJSMCIsIlIxIiksIGxhYmVscyA9IGMoIlIwIChuPTYwKSIsIlIxIChuPTI5KSIpKQpib3hwbG90KGN0RE5BLk1SRC5NVE1+UmVzTWFyZywgZGF0YT1jaXJjX2RhdGEsIG1haW49ImN0RE5BIE1SRCBNVE0gLSBSZXNlY3Rpb24gTWFyZ2luIiwgCiAgICAgICAgeGxhYj0iUmVzTWFyZyIsIHlsYWI9Ik1UTS9tTCIsIGNvbD0id2hpdGUiLCBib3JkZXI9ImJsYWNrIiwgeWxpbT1jKDAsIDEwKSkKbTIgPC0gd2lsY294LnRlc3QoY3RETkEuTVJELk1UTSB+IFJlc01hcmcsIGRhdGE9Y2lyY19kYXRhLCBuYS5ybT1UUlVFLCBleGFjdD1GQUxTRSwgY29uZi5pbnQ9VFJVRSkKcHJpbnQobTIpCgp0YWxseSh+UHJpbVNpdGUsIGRhdGE9Y2lyY19kYXRhLCBtYXJnaW5zID0gVFJVRSkKY2lyY19kYXRhJFByaW1TaXRlIDwtIGZhY3RvcihjaXJjX2RhdGEkUHJpbVNpdGUsIGxldmVscyA9IGMoInBDQ0EiLCJkQ0NBIiksIGxhYmVscyA9IGMoInBDQ0EgKG49NDMpIiwiZENDQSAobj00NikiKSkKYm94cGxvdChjdEROQS5NUkQuTVRNflByaW1TaXRlLCBkYXRhPWNpcmNfZGF0YSwgbWFpbj0iY3RETkEgTVJEIE1UTSAtIFByaW1hcnkgU2l0ZSIsIAogICAgICAgIHhsYWI9IlByaW1hcnkgU2l0ZSIsIHlsYWI9Ik1UTS9tTCIsIGNvbD0id2hpdGUiLCBib3JkZXI9ImJsYWNrIiwgeWxpbT1jKDAsIDEwKSkKbTMgPC0gd2lsY294LnRlc3QoY3RETkEuTVJELk1UTSB+IFByaW1TaXRlLCBkYXRhPWNpcmNfZGF0YSwgbmEucm09VFJVRSwgZXhhY3Q9RkFMU0UsIGNvbmYuaW50PVRSVUUpCnByaW50KG0zKQoKdGFsbHkoflN0YWdlLCBkYXRhPWNpcmNfZGF0YSwgbWFyZ2lucyA9IFRSVUUpCmNpcmNfZGF0YSRjdEROQS5NUkQuTVRNIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGNpcmNfZGF0YSRjdEROQS5NUkQuTVRNKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscyA9IGMoIklJIiwiSUlJIiwiSVYiKSwgbGFiZWxzID0gYygiSUkgKG49MzcpIiwgIklJSSAobj00MCkiLCJJViAobj0xMikiKSkKYm94cGxvdChjdEROQS5NUkQuTVRNflN0YWdlLCBkYXRhPWNpcmNfZGF0YSwgbWFpbj0iY3RETkEgTVJEIE1UTSAtIFN0YWdlIiwgCiAgICAgICAgeGxhYj0iU3RhZ2UiLCB5bGFiPSJNVE0vbUwiLCBjb2w9IndoaXRlIiwgYm9yZGVyPSJibGFjayIsIHlsaW09YygwLCAxMCkpCmtydXNrYWxfcmVzdWx0IDwtIGtydXNrYWwudGVzdChjdEROQS5NUkQuTVRNIH4gU3RhZ2UsIGRhdGE9Y2lyY19kYXRhKQpwcmludChrcnVza2FsX3Jlc3VsdCkKcGFpcndpc2Vfd2lsY294IDwtIHBhaXJ3aXNlLndpbGNveC50ZXN0KGNpcmNfZGF0YSRjdEROQS5NUkQuTVRNLCBjaXJjX2RhdGEkU3RhZ2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcC5hZGp1c3QubWV0aG9kID0gIkJIIiwgbmEucm0gPSBUUlVFKQpwcmludChwYWlyd2lzZV93aWxjb3gpCgp0YWxseSh+Q0ExOS5NUkQsIGRhdGE9Y2lyY19kYXRhLCBtYXJnaW5zID0gVFJVRSkKY2lyY19kYXRhJENBMTkuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkQ0ExOS5NUkQsIGxldmVscyA9IGMoIk5vcm1hbCIsIkVsZXZhdGVkIiksIGxhYmVscyA9IGMoIk5vcm1hbCAobj03NCkiLCJFbGV2YXRlZCAobj0xNSkiKSkKYm94cGxvdChjdEROQS5NUkQuTVRNfkNBMTkuTVJELCBkYXRhPWNpcmNfZGF0YSwgbWFpbj0iY3RETkEgTVJEIE1UTSAtIENBIDE5LTkiLCAKICAgICAgICB4bGFiPSJDQSAxOS05IiwgeWxhYj0iTVRNL21MIiwgY29sPSJ3aGl0ZSIsIGJvcmRlcj0iYmxhY2siLCB5bGltPWMoMCwgMTApKQptNCA8LSB3aWxjb3gudGVzdChjdEROQS5NUkQuTVRNIH4gQ0ExOS5NUkQsIGRhdGE9Y2lyY19kYXRhLCBuYS5ybT1UUlVFLCBleGFjdD1GQUxTRSwgY29uZi5pbnQ9VFJVRSkKcHJpbnQobTQpCmBgYAoKCiNNZWRpYW4gTVRNL21MIGxldmVscyBmb3IgY3RETkEgcG9zaXRpdmUgcHRzIGF0IE1SRApgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuTVJEPT0iUE9TSVRJVkUiLF0KCm1lZGlhbl9jdEROQSA8LSBtZWRpYW4oY2lyY19kYXRhJGN0RE5BLk1SRC5NVE0sIG5hLnJtID0gVFJVRSkKcmFuZ2VfY3RETkEgPC0gcmFuZ2UoY2lyY19kYXRhJGN0RE5BLk1SRC5NVE0sIG5hLnJtID0gVFJVRSkKY2F0KCJNZWRpYW4gTVRNL21MIHBvc3Qtc3VyZ2VyeToiLCBtZWRpYW5fY3RETkEsICJcbiIpCmNhdCgiUmFuZ2UgTVRNL21MIHBvc3Qtc3VyZ2VyeToiLCByYW5nZV9jdEROQVsxXSwgIi0iLCByYW5nZV9jdEROQVsyXSwgIlxuIikKYGBgCgoKI0Fzc29jaWF0aW9uIG9mIGN0RE5BIE1SRCBzdGF0dXMgd2l0aCBjbGluaWNvcGF0aG9sb2dpY2FsIGZhY3RvcnMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCgpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHMgPSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSIsICJjdEROQSgrKSIpKQpjaXJjX2RhdGEkcE4gPC0gZmFjdG9yKGNpcmNfZGF0YSRwTiwgbGV2ZWxzID0gYygiTjEiLCAiTjIiKSwgbGFiZWxzID0gYygicE4xIiwgInBOMiIpKQpjb250aW5nZW5jeV90YWJsZSA8LSB0YWJsZShjaXJjX2RhdGEkcE4sIGNpcmNfZGF0YSRjdEROQS5NUkQpCmNoaV9zcXVhcmVfdGVzdCA8LSBjaGlzcS50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChjaGlfc3F1YXJlX3Rlc3QpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmIDwtIGFzLmRhdGEuZnJhbWUoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmJFRvdGFsIDwtIGF2ZSh0YWJsZV9kZiRGcmVxLCB0YWJsZV9kZiRWYXIxLCBGVU4gPSBzdW0pCnRhYmxlX2RmJFBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkRnJlcSAvIHRhYmxlX2RmJFRvdGFsCnRhYmxlX2RmJE1pZGRsZVBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkUGVyY2VudGFnZSAvIDIKZ2dwbG90KHRhYmxlX2RmLCBhZXMoeCA9IFZhcjEsIHkgPSBQZXJjZW50YWdlLCBmaWxsID0gVmFyMikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fdGV4dChhZXMoeSA9IE1pZGRsZVBlcmNlbnRhZ2UsIGxhYmVsID0gRnJlcSksIHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IDEuNSwgc2l6ZSA9IDcpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiY3RETkEgc3RhdHVzIC0gcE4iLCAKICAgICAgIHggPSAicE4iLCAKICAgICAgIHkgPSAiUGF0aWVudHMgKCUpIiwgCiAgICAgICBmaWxsID0gImN0RE5BIE1SRCIsCiAgICAgICBjYXB0aW9uID0gcGFzdGUoIkZpc2hlcidzIGV4YWN0IHRlc3QgcC12YWx1ZTogIiwgZm9ybWF0LnB2YWwoZmlzaGVyX2V4YWN0X3Rlc3QkcC52YWx1ZSkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImN0RE5BKC0pIiA9ICJibHVlIiwgImN0RE5BKCspIiA9ICJyZWQiKSkgKyAjIGRlZmluZSBjdXN0b20gY29sb3JzCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBoanVzdCA9IDEuNSwgc2l6ZSA9IDE0KSwgIyBpbmNyZWFzZSB4LWF4aXMgdGV4dCBzaXplCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHktYXhpcyB0ZXh0IHNpemUKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHgtYXhpcyBsYWJlbCBzaXplCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB5LWF4aXMgbGFiZWwgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siKSkgICMgaW5jcmVhc2UgUHJvZ3Jlc3Npb24gbGFiZWwgc2l6ZQoKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKCmNpcmNfZGF0YSRjdEROQS5NUkQgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5NUkQsIGxldmVscyA9IGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIiksIGxhYmVscyA9IGMoImN0RE5BKC0pIiwgImN0RE5BKCspIikpCmNpcmNfZGF0YSRSZXNNYXJnIDwtIGZhY3RvcihjaXJjX2RhdGEkUmVzTWFyZywgbGV2ZWxzID0gYygiUjAiLCAiUjEiKSwgbGFiZWxzID0gYygiUjAiLCAiUjEiKSkKY29udGluZ2VuY3lfdGFibGUgPC0gdGFibGUoY2lyY19kYXRhJFJlc01hcmcsIGNpcmNfZGF0YSRjdEROQS5NUkQpCmNoaV9zcXVhcmVfdGVzdCA8LSBjaGlzcS50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChjaGlfc3F1YXJlX3Rlc3QpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmIDwtIGFzLmRhdGEuZnJhbWUoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmJFRvdGFsIDwtIGF2ZSh0YWJsZV9kZiRGcmVxLCB0YWJsZV9kZiRWYXIxLCBGVU4gPSBzdW0pCnRhYmxlX2RmJFBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkRnJlcSAvIHRhYmxlX2RmJFRvdGFsCnRhYmxlX2RmJE1pZGRsZVBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkUGVyY2VudGFnZSAvIDIKZ2dwbG90KHRhYmxlX2RmLCBhZXMoeCA9IFZhcjEsIHkgPSBQZXJjZW50YWdlLCBmaWxsID0gVmFyMikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fdGV4dChhZXMoeSA9IE1pZGRsZVBlcmNlbnRhZ2UsIGxhYmVsID0gRnJlcSksIHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IDEuNSwgc2l6ZSA9IDcpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiY3RETkEgc3RhdHVzIC0gTWFyZ2lucyIsIAogICAgICAgeCA9ICJNYXJnaW5zIiwgCiAgICAgICB5ID0gIlBhdGllbnRzICglKSIsIAogICAgICAgZmlsbCA9ICJjdEROQSBNUkQiLAogICAgICAgY2FwdGlvbiA9IHBhc3RlKCJGaXNoZXIncyBleGFjdCB0ZXN0IHAtdmFsdWU6ICIsIGZvcm1hdC5wdmFsKGZpc2hlcl9leGFjdF90ZXN0JHAudmFsdWUpKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjdEROQSgtKSIgPSAiYmx1ZSIsICJjdEROQSgrKSIgPSAicmVkIikpICsgIyBkZWZpbmUgY3VzdG9tIGNvbG9ycwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxNCksICMgaW5jcmVhc2UgeC1heGlzIHRleHQgc2l6ZQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB5LWF4aXMgdGV4dCBzaXplCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB4LWF4aXMgbGFiZWwgc2l6ZQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeS1heGlzIGxhYmVsIHNpemUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImJsYWNrIikpICAjIGluY3JlYXNlIFByb2dyZXNzaW9uIGxhYmVsIHNpemUKCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCgpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHMgPSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSIsICJjdEROQSgrKSIpKQpjaXJjX2RhdGEkUHJpbVNpdGUgPC0gZmFjdG9yKGNpcmNfZGF0YSRQcmltU2l0ZSwgbGV2ZWxzID0gYygicENDQSIsICJkQ0NBIiksIGxhYmVscyA9IGMoInBDQ0EiLCAiZENDQSIpKQpjb250aW5nZW5jeV90YWJsZSA8LSB0YWJsZShjaXJjX2RhdGEkUHJpbVNpdGUsIGNpcmNfZGF0YSRjdEROQS5NUkQpCmNoaV9zcXVhcmVfdGVzdCA8LSBjaGlzcS50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChjaGlfc3F1YXJlX3Rlc3QpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmIDwtIGFzLmRhdGEuZnJhbWUoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmJFRvdGFsIDwtIGF2ZSh0YWJsZV9kZiRGcmVxLCB0YWJsZV9kZiRWYXIxLCBGVU4gPSBzdW0pCnRhYmxlX2RmJFBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkRnJlcSAvIHRhYmxlX2RmJFRvdGFsCnRhYmxlX2RmJE1pZGRsZVBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkUGVyY2VudGFnZSAvIDIKZ2dwbG90KHRhYmxlX2RmLCBhZXMoeCA9IFZhcjEsIHkgPSBQZXJjZW50YWdlLCBmaWxsID0gVmFyMikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fdGV4dChhZXMoeSA9IE1pZGRsZVBlcmNlbnRhZ2UsIGxhYmVsID0gRnJlcSksIHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IDEuNSwgc2l6ZSA9IDcpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiY3RETkEgc3RhdHVzIC0gUHJpbWFyeSBTaXRlIiwgCiAgICAgICB4ID0gIlByaW1hcnkgU2l0ZSIsIAogICAgICAgeSA9ICJQYXRpZW50cyAoJSkiLCAKICAgICAgIGZpbGwgPSAiY3RETkEgTVJEIiwKICAgICAgIGNhcHRpb24gPSBwYXN0ZSgiRmlzaGVyJ3MgZXhhY3QgdGVzdCBwLXZhbHVlOiAiLCBmb3JtYXQucHZhbChmaXNoZXJfZXhhY3RfdGVzdCRwLnZhbHVlKSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiY3RETkEoLSkiID0gImJsdWUiLCAiY3RETkEoKykiID0gInJlZCIpKSArICMgZGVmaW5lIGN1c3RvbSBjb2xvcnMKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMS41LCBzaXplID0gMTQpLCAjIGluY3JlYXNlIHgtYXhpcyB0ZXh0IHNpemUKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeS1heGlzIHRleHQgc2l6ZQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeC1heGlzIGxhYmVsIHNpemUKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHktYXhpcyBsYWJlbCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIpKSAgIyBpbmNyZWFzZSBQcm9ncmVzc2lvbiBsYWJlbCBzaXplCgpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQoKY2lyY19kYXRhJGN0RE5BLk1SRCA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLk1SRCwgbGV2ZWxzID0gYygiTkVHQVRJVkUiLCAiUE9TSVRJVkUiKSwgbGFiZWxzID0gYygiY3RETkEoLSkiLCAiY3RETkEoKykiKSkKY2lyY19kYXRhJFN0YWdlIDwtIGZhY3RvcihjaXJjX2RhdGEkU3RhZ2UsIGxldmVscyA9IGMoIklJIiwgIklJSSIsICJJViIpLCBsYWJlbHMgPSBjKCJJSSIsICJJSUkiLCAiSVYiKSkKY29udGluZ2VuY3lfdGFibGUgPC0gdGFibGUoY2lyY19kYXRhJFN0YWdlLCBjaXJjX2RhdGEkY3RETkEuTVJEKQpjaGlfc3F1YXJlX3Rlc3QgPC0gY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoY2hpX3NxdWFyZV90ZXN0KQpmaXNoZXJfZXhhY3RfdGVzdCA8LSBmaXNoZXIudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoZmlzaGVyX2V4YWN0X3Rlc3QpCnByaW50KGNvbnRpbmdlbmN5X3RhYmxlKQp0YWJsZV9kZiA8LSBhcy5kYXRhLmZyYW1lKGNvbnRpbmdlbmN5X3RhYmxlKQp0YWJsZV9kZiRUb3RhbCA8LSBhdmUodGFibGVfZGYkRnJlcSwgdGFibGVfZGYkVmFyMSwgRlVOID0gc3VtKQp0YWJsZV9kZiRQZXJjZW50YWdlIDwtIHRhYmxlX2RmJEZyZXEgLyB0YWJsZV9kZiRUb3RhbAp0YWJsZV9kZiRNaWRkbGVQZXJjZW50YWdlIDwtIHRhYmxlX2RmJFBlcmNlbnRhZ2UgLyAyCmdncGxvdCh0YWJsZV9kZiwgYWVzKHggPSBWYXIxLCB5ID0gUGVyY2VudGFnZSwgZmlsbCA9IFZhcjIpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX3RleHQoYWVzKHkgPSBNaWRkbGVQZXJjZW50YWdlLCBsYWJlbCA9IEZyZXEpLCBwb3NpdGlvbiA9ICJzdGFjayIsIGNvbG9yID0gImJsYWNrIiwgdmp1c3QgPSAxLjUsIHNpemUgPSA3KSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gImN0RE5BIHN0YXR1cyAtIFN0YWdlIiwgCiAgICAgICB4ID0gIlN0YWdlIiwgCiAgICAgICB5ID0gIlBhdGllbnRzICglKSIsIAogICAgICAgZmlsbCA9ICJjdEROQSBNUkQiLAogICAgICAgY2FwdGlvbiA9IHBhc3RlKCJGaXNoZXIncyBleGFjdCB0ZXN0IHAtdmFsdWU6ICIsIGZvcm1hdC5wdmFsKGZpc2hlcl9leGFjdF90ZXN0JHAudmFsdWUpKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjdEROQSgtKSIgPSAiYmx1ZSIsICJjdEROQSgrKSIgPSAicmVkIikpICsgIyBkZWZpbmUgY3VzdG9tIGNvbG9ycwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxNCksICMgaW5jcmVhc2UgeC1heGlzIHRleHQgc2l6ZQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB5LWF4aXMgdGV4dCBzaXplCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB4LWF4aXMgbGFiZWwgc2l6ZQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeS1heGlzIGxhYmVsIHNpemUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImJsYWNrIikpICAjIGluY3JlYXNlIFByb2dyZXNzaW9uIGxhYmVsIHNpemUKCnBhaXJ3aXNlX2Zpc2hlciA8LSBmdW5jdGlvbihkYXRhLCBmYWN0b3IxLCBmYWN0b3IyKSB7CiAgbGV2ZWxzIDwtIHVuaXF1ZShkYXRhW1tmYWN0b3IxXV0pCiAgcmVzdWx0cyA8LSBkYXRhLmZyYW1lKFN0YWdlMSA9IGNoYXJhY3RlcigpLCBTdGFnZTIgPSBjaGFyYWN0ZXIoKSwgcC52YWx1ZSA9IG51bWVyaWMoKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQogIAogIGZvciAoaSBpbiAxOihsZW5ndGgobGV2ZWxzKSAtIDEpKSB7CiAgICBmb3IgKGogaW4gKGkgKyAxKTpsZW5ndGgobGV2ZWxzKSkgewogICAgICBzdWJzZXRfZGF0YSA8LSBkYXRhICU+JSBmaWx0ZXIoZGF0YVtbZmFjdG9yMV1dICVpbiUgYyhsZXZlbHNbaV0sIGxldmVsc1tqXSkpCiAgICAgIGNvbnRpbmdlbmN5X3RhYmxlX3BhaXJ3aXNlIDwtIHRhYmxlKHN1YnNldF9kYXRhW1tmYWN0b3IxXV0sIHN1YnNldF9kYXRhW1tmYWN0b3IyXV0pCiAgICAgIGZpc2hlcl9yZXN1bHQgPC0gZmlzaGVyLnRlc3QoY29udGluZ2VuY3lfdGFibGVfcGFpcndpc2UpCiAgICAgIHJlc3VsdHMgPC0gcmJpbmQocmVzdWx0cywgZGF0YS5mcmFtZShTdGFnZTEgPSBsZXZlbHNbaV0sIFN0YWdlMiA9IGxldmVsc1tqXSwgcC52YWx1ZSA9IGZpc2hlcl9yZXN1bHQkcC52YWx1ZSkpCiAgICB9CiAgfQogIHJldHVybihyZXN1bHRzKQp9CgojIFBlcmZvcm0gcGFpcndpc2UgY29tcGFyaXNvbnMKcGFpcndpc2VfcmVzdWx0cyA8LSBwYWlyd2lzZV9maXNoZXIoY2lyY19kYXRhLCAiU3RhZ2UiLCAiY3RETkEuTVJEIikKcHJpbnQocGFpcndpc2VfcmVzdWx0cykKCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCgpjaXJjX2RhdGEkY3RETkEuTVJEIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuTVJELCBsZXZlbHMgPSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpLCBsYWJlbHMgPSBjKCJjdEROQSgtKSIsICJjdEROQSgrKSIpKQpjaXJjX2RhdGEkQ0ExOS5NUkQgPC0gZmFjdG9yKGNpcmNfZGF0YSRDQTE5Lk1SRCwgbGV2ZWxzID0gYygiTm9ybWFsIiwgIkVsZXZhdGVkIiksIGxhYmVscyA9IGMoIk5vcm1hbCIsICJFbGV2YXRlZCIpKQpjb250aW5nZW5jeV90YWJsZSA8LSB0YWJsZShjaXJjX2RhdGEkQ0ExOS5NUkQsIGNpcmNfZGF0YSRjdEROQS5NUkQpCmNoaV9zcXVhcmVfdGVzdCA8LSBjaGlzcS50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChjaGlfc3F1YXJlX3Rlc3QpCmZpc2hlcl9leGFjdF90ZXN0IDwtIGZpc2hlci50ZXN0KGNvbnRpbmdlbmN5X3RhYmxlKQpwcmludChmaXNoZXJfZXhhY3RfdGVzdCkKcHJpbnQoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmIDwtIGFzLmRhdGEuZnJhbWUoY29udGluZ2VuY3lfdGFibGUpCnRhYmxlX2RmJFRvdGFsIDwtIGF2ZSh0YWJsZV9kZiRGcmVxLCB0YWJsZV9kZiRWYXIxLCBGVU4gPSBzdW0pCnRhYmxlX2RmJFBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkRnJlcSAvIHRhYmxlX2RmJFRvdGFsCnRhYmxlX2RmJE1pZGRsZVBlcmNlbnRhZ2UgPC0gdGFibGVfZGYkUGVyY2VudGFnZSAvIDIKZ2dwbG90KHRhYmxlX2RmLCBhZXMoeCA9IFZhcjEsIHkgPSBQZXJjZW50YWdlLCBmaWxsID0gVmFyMikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fdGV4dChhZXMoeSA9IE1pZGRsZVBlcmNlbnRhZ2UsIGxhYmVsID0gRnJlcSksIHBvc2l0aW9uID0gInN0YWNrIiwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IDEuNSwgc2l6ZSA9IDcpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiY3RETkEgc3RhdHVzIC0gQ0EgMTktOSIsIAogICAgICAgeCA9ICJDQSAxOS05IiwgCiAgICAgICB5ID0gIlBhdGllbnRzICglKSIsIAogICAgICAgZmlsbCA9ICJjdEROQSBNUkQiLAogICAgICAgY2FwdGlvbiA9IHBhc3RlKCJGaXNoZXIncyBleGFjdCB0ZXN0IHAtdmFsdWU6ICIsIGZvcm1hdC5wdmFsKGZpc2hlcl9leGFjdF90ZXN0JHAudmFsdWUpKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjdEROQSgtKSIgPSAiYmx1ZSIsICJjdEROQSgrKSIgPSAicmVkIikpICsgIyBkZWZpbmUgY3VzdG9tIGNvbG9ycwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxLjUsIHNpemUgPSAxNCksICMgaW5jcmVhc2UgeC1heGlzIHRleHQgc2l6ZQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB5LWF4aXMgdGV4dCBzaXplCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiYmxhY2siKSwgIyBpbmNyZWFzZSB4LWF4aXMgbGFiZWwgc2l6ZQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeS1heGlzIGxhYmVsIHNpemUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImJsYWNrIikpICAjIGluY3JlYXNlIFByb2dyZXNzaW9uIGxhYmVsIHNpemUKYGBgCgojUHJvZ25vc3RpYyByb2xlIG9mIGN0RE5BIGF0IEM1RDEKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkM1RDEhPSIiLF0KY2lyY19kYXRhJFJGUy5tb250aHM9Y2lyY19kYXRhJFJGUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRSRlMubW9udGhzPj0wLF0KY2lyY19kYXRhJFJGUy5tb250aHNbY2lyY19kYXRhJFJGUy5tb250aHMgPiA2MF0gPC0gNjAKY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpfmN0RE5BLkM1RDEsIGRhdGEgPSBjaXJjX2RhdGEpCmV2ZW50X3N1bW1hcnkgPC0gY2lyY19kYXRhICU+JQogIGdyb3VwX2J5KGN0RE5BLkM1RDEpICU+JQogIHN1bW1hcmlzZSgKICAgIFRvdGFsID0gbigpLAogICAgRXZlbnRzID0gc3VtKFJGUy5FdmVudCksCiAgICBGcmFjdGlvbiA9IEV2ZW50cyAvIG4oKSwKICAgIFBlcmNlbnRhZ2UgPSAoRXZlbnRzIC8gbigpKSAqIDEwMAogICkKcHJpbnQoZXZlbnRfc3VtbWFyeSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkUkZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkUkZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQzVEMSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9IkRGUyAtIGN0RE5BIEM1RDEiLCB5bGFiPSAiRGlzZWFzZSBGcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMTIsIDI0KSkKY2lyY19kYXRhJGN0RE5BLkM1RDEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DNUQxLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzVEMSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKI011bHRpdmFyaWF0ZSByZWdyZXNzaW9uIG1vZGVsIGZvciBERlMgd2l0aCBjdEROQSBhbmQgQ0EgMTktOQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsICFpcy5uYShjdEROQS5DNUQxKSkKY2lyY19kYXRhJFJGUy5tb250aHM9Y2lyY19kYXRhJFJGUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRSRlMubW9udGhzPj0wLF0KY2lyY19kYXRhJFJGUy5tb250aHNbY2lyY19kYXRhJFJGUy5tb250aHMgPiA2MF0gPC0gNjAKY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCmNpcmNfZGF0YWRmJFNleCA8LSBmYWN0b3IoY2lyY19kYXRhZGYkU2V4LCBsZXZlbHMgPSBjKCJGZW1hbGUiLCAiTWFsZSIpLCBsYWJlbHMgPSBjKCJGZW1hbGUiLCAiTWFsZSIpKQpjaXJjX2RhdGFkZiRQcmltU2l0ZSA8LSBmYWN0b3IoY2lyY19kYXRhZGYkUHJpbVNpdGUsIGxldmVscyA9IGMoInBDQ0EiLCAiZENDQSIpLCBsYWJlbHMgPSBjKCJwQ0NBIiwgImRDQ0EiKSkKY2lyY19kYXRhZGYkQ2hlbW8gPC0gZmFjdG9yKGNpcmNfZGF0YWRmJENoZW1vLCBsZXZlbHMgPSBjKCJDQVAiLCAiR2VtQ2lzIiksIGxhYmVscyA9IGMoIkNBUCIsICJHZW1DaXMiKSkKY2lyY19kYXRhZGYkUmVzTWFyZyA8LSBmYWN0b3IoY2lyY19kYXRhZGYkUmVzTWFyZywgbGV2ZWxzID0gYygiUjAiLCAiUjEiKSkKY2lyY19kYXRhZGYkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YWRmJFN0YWdlLCBsZXZlbHMgPSBjKCJJSSIsICJJSUkiLCAiSVYiKSwgbGFiZWxzID0gYygiSUkiLCAiSUlJIiwgIklWIikpCmNpcmNfZGF0YWRmJFRQNTMgPC0gZmFjdG9yKGNpcmNfZGF0YWRmJFRQNTMsIGxldmVscyA9IGMoIldUIiwgIk11dCIpKQpjaXJjX2RhdGFkZiRDQTE5LkM1RDEgPC0gZmFjdG9yKGNpcmNfZGF0YWRmJENBMTkuQzVEMSwgbGV2ZWxzID0gYygiTm9ybWFsIiwgIkVsZXZhdGVkIikpCmNpcmNfZGF0YWRmJGN0RE5BLkM1RDEgPC0gZmFjdG9yKGNpcmNfZGF0YWRmJGN0RE5BLkM1RDEsIGxldmVscyA9IGMoIk5FR0FUSVZFIiwgIlBPU0lUSVZFIiksIGxhYmVscyA9IGMoIk5lZ2F0aXZlIiwgIlBvc2l0aXZlIikpCnN1cnZfb2JqZWN0PC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGFkZiRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YWRmJFJGUy5FdmVudCkgCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBTZXggKyBBZ2UgKyBQcmltU2l0ZSArIFN0YWdlICsgQ2hlbW8gKyBSZXNNYXJnICsgQ0ExOS5DNUQxICsgY3RETkEuQzVEMSwgZGF0YT1jaXJjX2RhdGFkZikgCmdnZm9yZXN0KGNveF9maXQsIGRhdGEgPSBjaXJjX2RhdGFkZiwgbWFpbiA9ICJNdWx0aXZhcmlhdGUgUmVncmVzc2lvbiBNb2RlbCBmb3IgREZTIC0gTGFuZG1hcmsgYW5hbHlzaXMiLCByZWZMYWJlbCA9ICJSZWZlcmVuY2UgR3JvdXAiKQp0ZXN0LnBoIDwtIGNveC56cGgoY294X2ZpdCkKYGBgCgojVW5pdmFyaWF0ZSByZWdyZXNzaW9uIG1vZGVsIGZvciBmYWN0b3JzIHVzZWQgYXQgdGhlIEM1RDEgTVZBCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgIWlzLm5hKGN0RE5BLkM1RDEpKQpjaXJjX2RhdGEkUkZTLm1vbnRocz1jaXJjX2RhdGEkUkZTLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJFJGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkUkZTLm1vbnRoc1tjaXJjX2RhdGEkUkZTLm1vbnRocyA+IDYwXSA8LSA2MApzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpCmNpcmNfZGF0YSRTZXggPC0gZmFjdG9yKGNpcmNfZGF0YSRTZXgsIGxldmVscyA9IGMoIkZlbWFsZSIsICJNYWxlIiksIGxhYmVscyA9IGMoIkZlbWFsZSIsICJNYWxlIikpICN1bml2YXJpYXRlIGZvciBnZW5kZXIKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IFNleCwgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCgpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgIWlzLm5hKGN0RE5BLkM1RDEpKQpjaXJjX2RhdGEkUkZTLm1vbnRocz1jaXJjX2RhdGEkUkZTLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJFJGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkUkZTLm1vbnRoc1tjaXJjX2RhdGEkUkZTLm1vbnRocyA+IDYwXSA8LSA2MApzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBBZ2UsIGRhdGE9Y2lyY19kYXRhKSAjdW5pdmFyaWF0ZSBmb3IgYWdlCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCgpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgIWlzLm5hKGN0RE5BLkM1RDEpKQpjaXJjX2RhdGEkUkZTLm1vbnRocz1jaXJjX2RhdGEkUkZTLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJFJGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkUkZTLm1vbnRoc1tjaXJjX2RhdGEkUkZTLm1vbnRocyA+IDYwXSA8LSA2MApzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpCmNpcmNfZGF0YSRQcmltU2l0ZSA8LSBmYWN0b3IoY2lyY19kYXRhJFByaW1TaXRlLCBsZXZlbHMgPSBjKCJwQ0NBIiwgImRDQ0EiKSwgbGFiZWxzID0gYygicENDQSIsICJkQ0NBIikpICN1bml2YXJpYXRlIGZvciBQcmltYXJ5IFNpdGUKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IFByaW1TaXRlLCBkYXRhPWNpcmNfZGF0YSkKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCAhaXMubmEoY3RETkEuQzVEMSkpCmNpcmNfZGF0YSRSRlMubW9udGhzPWNpcmNfZGF0YSRSRlMubW9udGhzLTIKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkUkZTLm1vbnRocz49MCxdCmNpcmNfZGF0YSRSRlMubW9udGhzW2NpcmNfZGF0YSRSRlMubW9udGhzID4gNjBdIDwtIDYwCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IFN0YWdlLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBUUlVFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0zLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInJlZCIpLCB0aXRsZT0iREZTIC0gY3RETkEgQzVEMSAtIFN0YWdlIiwgeWxhYj0gIkRpc2Vhc2UgRnJlZSBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJJSSIsICJJSUkiLCAiSVYiKSwgbGVnZW5kLnRpdGxlPSIiKQpjaXJjX2RhdGEkU3RhZ2UgPC0gZmFjdG9yKGNpcmNfZGF0YSRTdGFnZSwgbGV2ZWxzID0gYygiSUkiLCAiSUlJIiwgIklWIiksIGxhYmVscyA9IGMoIklJIiwgIklJSSIsICJJViIpKSAjdW5pdmFyaWF0ZSBmb3IgU3RhZ2UKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IFN0YWdlLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCAhaXMubmEoY3RETkEuQzVEMSkpCmNpcmNfZGF0YSRSRlMubW9udGhzPWNpcmNfZGF0YSRSRlMubW9udGhzLTIKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkUkZTLm1vbnRocz49MCxdCmNpcmNfZGF0YSRSRlMubW9udGhzW2NpcmNfZGF0YSRSRlMubW9udGhzID4gNjBdIDwtIDYwCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCkKY2lyY19kYXRhJENoZW1vIDwtIGZhY3RvcihjaXJjX2RhdGEkQ2hlbW8sIGxldmVscyA9IGMoIkNBUCIsICJHZW1DaXMiKSwgbGFiZWxzID0gYygiQ0FQIiwgIkdlbUNpcyIpKSAjdW5pdmFyaWF0ZSBmb3IgQ2hlbW90aGVyYXB5CmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBDaGVtbywgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCgpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgIWlzLm5hKGN0RE5BLkM1RDEpKQpjaXJjX2RhdGEkUkZTLm1vbnRocz1jaXJjX2RhdGEkUkZTLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJFJGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkUkZTLm1vbnRoc1tjaXJjX2RhdGEkUkZTLm1vbnRocyA+IDYwXSA8LSA2MApzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpCmNpcmNfZGF0YSRSZXNNYXJnIDwtIGZhY3RvcihjaXJjX2RhdGEkUmVzTWFyZywgbGV2ZWxzID0gYygiUjAiLCAiUjEiKSkgI3VuaXZhcmlhdGUgZm9yIFJlc2VjdGlvbiBtYXJnaW4KY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IFJlc01hcmcsIGRhdGE9Y2lyY19kYXRhKQpzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQoKcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsICFpcy5uYShjdEROQS5DNUQxKSkKY2lyY19kYXRhJFJGUy5tb250aHM9Y2lyY19kYXRhJFJGUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRSRlMubW9udGhzPj0wLF0KY2lyY19kYXRhJFJGUy5tb250aHNbY2lyY19kYXRhJFJGUy5tb250aHMgPiA2MF0gPC0gNjAKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkUkZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkUkZTLkV2ZW50KQpjaXJjX2RhdGEkQ0ExOS5DNUQxIDwtIGZhY3RvcihjaXJjX2RhdGEkQ0ExOS5DNUQxLCBsZXZlbHMgPSBjKCJOb3JtYWwiLCAiRWxldmF0ZWQiKSkgI3VuaXZhcmlhdGUgZm9yIENBIDE5LTkgQzVEMQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gQ0ExOS5DNUQxLCBkYXRhPWNpcmNfZGF0YSkKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKCnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCAhaXMubmEoY3RETkEuQzVEMSkpCmNpcmNfZGF0YSRSRlMubW9udGhzPWNpcmNfZGF0YSRSRlMubW9udGhzLTIKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkUkZTLm1vbnRocz49MCxdCmNpcmNfZGF0YSRSRlMubW9udGhzW2NpcmNfZGF0YSRSRlMubW9udGhzID4gNjBdIDwtIDYwCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCkKY2lyY19kYXRhJGN0RE5BLkM1RDEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DNUQxLCBsZXZlbHMgPSBjKCJORUdBVElWRSIsICJQT1NJVElWRSIpLCBsYWJlbHMgPSBjKCJOZWdhdGl2ZSIsICJQb3NpdGl2ZSIpKSAjdW5pdmFyaWF0ZSBmb3IgY3RETkEgQzVEMQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzVEMSwgZGF0YT1jaXJjX2RhdGEpCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKI09TIGJ5IGN0RE5BIGF0IEM1RDEKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLkM1RDEhPSIiLF0KY2lyY19kYXRhJE9TLm1vbnRocz1jaXJjX2RhdGEkT1MubW9udGhzLTIKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkT1MubW9udGhzPj0wLF0KY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRPUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KX5jdEROQS5DNUQxLCBkYXRhID0gY2lyY19kYXRhKQpldmVudF9zdW1tYXJ5IDwtIGNpcmNfZGF0YSAlPiUKICBncm91cF9ieShjdEROQS5DNUQxKSAlPiUKICBzdW1tYXJpc2UoCiAgICBUb3RhbCA9IG4oKSwKICAgIEV2ZW50cyA9IHN1bShPUy5FdmVudCksCiAgICBGcmFjdGlvbiA9IEV2ZW50cyAvIG4oKSwKICAgIFBlcmNlbnRhZ2UgPSAoRXZlbnRzIC8gbigpKSAqIDEwMAogICkKcHJpbnQoZXZlbnRfc3VtbWFyeSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkT1MubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLkM1RDEsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwicmVkIiksIHRpdGxlPSJPUyAtIGN0RE5BIEM1RDEiLCB5bGFiPSAiT3ZlcmFsbCBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgKE1vbnRocykiLCBsZWdlbmQubGFicz1jKCJjdEROQSBOZWdhdGl2ZSIsICJjdEROQSBQb3NpdGl2ZSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDEyLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5DNUQxIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQzVEMSwgbGV2ZWxzPWMoIk5FR0FUSVZFIiwiUE9TSVRJVkUiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkM1RDEsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQoKIyBFeHRyYWN0IHZhbHVlcyBmb3IgSFIsIDk1JSBDSSwgYW5kIHAtdmFsdWUKSFIgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syXQpsb3dlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbM10KdXBwZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzRdCnBfdmFsdWUgPC0gY294X2ZpdF9zdW1tYXJ5JGNvZWZmaWNpZW50c1s1XQpsYWJlbF90ZXh0IDwtIHBhc3RlMCgiSFIgPSAiLCByb3VuZChIUiwgMiksICIgKCIsIHJvdW5kKGxvd2VyX0NJLCAyKSwgIi0iLCByb3VuZCh1cHBlcl9DSSwgMiksICIpOyBwID0gIiwgcm91bmQocF92YWx1ZSwgMykpCnByaW50KGxhYmVsX3RleHQpCmBgYAoKCiNQcm9nbm9zdGljIHJvbGUgb2YgY3RETkEgYXQgQzhEMQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzhEMSE9IiIsXQpjaXJjX2RhdGEkUkZTLm1vbnRocz1jaXJjX2RhdGEkUkZTLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJFJGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkUkZTLm1vbnRoc1tjaXJjX2RhdGEkUkZTLm1vbnRocyA+IDYwXSA8LSA2MApjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCl+Y3RETkEuQzhEMSwgZGF0YSA9IGNpcmNfZGF0YSkKZXZlbnRfc3VtbWFyeSA8LSBjaXJjX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY3RETkEuQzhEMSkgJT4lCiAgc3VtbWFyaXNlKAogICAgVG90YWwgPSBuKCksCiAgICBFdmVudHMgPSBzdW0oUkZTLkV2ZW50KSwKICAgIEZyYWN0aW9uID0gRXZlbnRzIC8gbigpLAogICAgUGVyY2VudGFnZSA9IChFdmVudHMgLyBuKCkpICogMTAwCiAgKQpwcmludChldmVudF9zdW1tYXJ5KQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5DOEQxLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iREZTIC0gY3RETkEgQzhEMSIsIHlsYWI9ICJEaXNlYXNlIEZyZWUgU3Vydml2YWwiLCB4bGFiPSJUaW1lIChNb250aHMpIiwgbGVnZW5kLmxhYnM9YygiY3RETkEgTmVnYXRpdmUiLCAiY3RETkEgUG9zaXRpdmUiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygxMiwgMjQpKQpjaXJjX2RhdGEkY3RETkEuQzhEMSA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkM4RDEsIGxldmVscz1jKCJORUdBVElWRSIsIlBPU0lUSVZFIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5DOEQxLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKCiMgRXh0cmFjdCB2YWx1ZXMgZm9yIEhSLCA5NSUgQ0ksIGFuZCBwLXZhbHVlCkhSIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbMl0KbG93ZXJfQ0kgPC0gY294X2ZpdF9zdW1tYXJ5JGNvbmYuaW50WzNdCnVwcGVyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFs0XQpwX3ZhbHVlIDwtIGNveF9maXRfc3VtbWFyeSRjb2VmZmljaWVudHNbNV0KbGFiZWxfdGV4dCA8LSBwYXN0ZTAoIkhSID0gIiwgcm91bmQoSFIsIDIpLCAiICgiLCByb3VuZChsb3dlcl9DSSwgMiksICItIiwgcm91bmQodXBwZXJfQ0ksIDIpLCAiKTsgcCA9ICIsIHJvdW5kKHBfdmFsdWUsIDMpKQpwcmludChsYWJlbF90ZXh0KQpgYGAKCgojT1MgYnkgY3RETkEgYXQgQzhEMQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuQzhEMSE9IiIsXQpjaXJjX2RhdGEkT1MubW9udGhzPWNpcmNfZGF0YSRPUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRPUy5tb250aHM+PTAsXQpjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJE9TLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpfmN0RE5BLkM4RDEsIGRhdGEgPSBjaXJjX2RhdGEpCmV2ZW50X3N1bW1hcnkgPC0gY2lyY19kYXRhICU+JQogIGdyb3VwX2J5KGN0RE5BLkM4RDEpICU+JQogIHN1bW1hcmlzZSgKICAgIFRvdGFsID0gbigpLAogICAgRXZlbnRzID0gc3VtKE9TLkV2ZW50KSwKICAgIEZyYWN0aW9uID0gRXZlbnRzIC8gbigpLAogICAgUGVyY2VudGFnZSA9IChFdmVudHMgLyBuKCkpICogMTAwCiAgKQpwcmludChldmVudF9zdW1tYXJ5KQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRPUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJE9TLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQzhEMSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJyZWQiKSwgdGl0bGU9Ik9TIC0gY3RETkEgQzhEMSIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMTIsIDI0KSkKY2lyY19kYXRhJGN0RE5BLkM4RDEgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DOEQxLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzhEMSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKI1Byb2dub3N0aWMgcm9sZSBvZiBjdEROQSBhbnl0aW1lIHBvc3Qtc3VyZ2VyeQpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkY3RETkEuYW55dGltZSE9IiIsXQpjaXJjX2RhdGEkUkZTLm1vbnRocz1jaXJjX2RhdGEkUkZTLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJFJGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkUkZTLm1vbnRoc1tjaXJjX2RhdGEkUkZTLm1vbnRocyA+IDYwXSA8LSA2MApjaXJjX2RhdGFkZiA8LSBhcy5kYXRhLmZyYW1lKGNpcmNfZGF0YSkKCnN1cnZmaXQoU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCl+Y3RETkEuYW55dGltZSwgZGF0YSA9IGNpcmNfZGF0YSkKZXZlbnRfc3VtbWFyeSA8LSBjaXJjX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY3RETkEuYW55dGltZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgVG90YWwgPSBuKCksCiAgICBFdmVudHMgPSBzdW0oUkZTLkV2ZW50KSwKICAgIEZyYWN0aW9uID0gRXZlbnRzIC8gbigpLAogICAgUGVyY2VudGFnZSA9IChFdmVudHMgLyBuKCkpICogMTAwCiAgKQpwcmludChldmVudF9zdW1tYXJ5KQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5hbnl0aW1lLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iREZTIC0gY3RETkEgYW55dGltZSBwb3N0LXN1cmdlcnkiLCB5bGFiPSAiRGlzZWFzZSBGcmVlIFN1cnZpdmFsIiwgeGxhYj0iVGltZSAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMTIsIDI0KSkKY2lyY19kYXRhJGN0RE5BLmFueXRpbWUgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5hbnl0aW1lLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuYW55dGltZSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKI09TIGJ5IGN0RE5BIGFueXRpbWUgcG9zdC1zdXJnZXJ5CmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRjdEROQS5hbnl0aW1lIT0iIixdCmNpcmNfZGF0YSRPUy5tb250aHM9Y2lyY19kYXRhJE9TLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJE9TLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkT1MubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuYW55dGltZSwgZGF0YSA9IGNpcmNfZGF0YSkKZXZlbnRfc3VtbWFyeSA8LSBjaXJjX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY3RETkEuYW55dGltZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgVG90YWwgPSBuKCksCiAgICBFdmVudHMgPSBzdW0oT1MuRXZlbnQpLAogICAgRnJhY3Rpb24gPSBFdmVudHMgLyBuKCksCiAgICBQZXJjZW50YWdlID0gKEV2ZW50cyAvIG4oKSkgKiAxMDAKICApCnByaW50KGV2ZW50X3N1bW1hcnkpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJE9TLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkT1MuRXZlbnQpCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5hbnl0aW1lLCBkYXRhID0gY2lyY19kYXRhLGNvbmYuaW50PTAuOTUsY29uZi50eXBlPSJsb2ctbG9nIikgCmdnc3VydnBsb3QoS01fY3VydmUsIGRhdGEgPSBjaXJjX2RhdGEsIHB2YWwgPSBGQUxTRSwgY29uZi5pbnQgPSBGQUxTRSwgcmlzay50YWJsZSA9IFRSVUUsIGJyZWFrLnRpbWUuYnk9MTIsIHBhbGV0dGU9YygiYmx1ZSIsInJlZCIpLCB0aXRsZT0iT1MgLSBjdEROQSBhbnl0aW1lIHBvc3Qtc3VyZ2VyeSIsIHlsYWI9ICJPdmVyYWxsIFN1cnZpdmFsIiwgeGxhYj0iVGltZSAoTW9udGhzKSIsIGxlZ2VuZC5sYWJzPWMoImN0RE5BIE5lZ2F0aXZlIiwgImN0RE5BIFBvc2l0aXZlIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMTIsIDI0KSkKY2lyY19kYXRhJGN0RE5BLmFueXRpbWUgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5hbnl0aW1lLCBsZXZlbHM9YygiTkVHQVRJVkUiLCJQT1NJVElWRSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuYW55dGltZSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCgojIEV4dHJhY3QgdmFsdWVzIGZvciBIUiwgOTUlIENJLCBhbmQgcC12YWx1ZQpIUiA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzJdCmxvd2VyX0NJIDwtIGNveF9maXRfc3VtbWFyeSRjb25mLmludFszXQp1cHBlcl9DSSA8LSBjb3hfZml0X3N1bW1hcnkkY29uZi5pbnRbNF0KcF92YWx1ZSA8LSBjb3hfZml0X3N1bW1hcnkkY29lZmZpY2llbnRzWzVdCmxhYmVsX3RleHQgPC0gcGFzdGUwKCJIUiA9ICIsIHJvdW5kKEhSLCAyKSwgIiAoIiwgcm91bmQobG93ZXJfQ0ksIDIpLCAiLSIsIHJvdW5kKHVwcGVyX0NJLCAyKSwgIik7IHAgPSAiLCByb3VuZChwX3ZhbHVlLCAzKSkKcHJpbnQobGFiZWxfdGV4dCkKYGBgCgoKI1Byb2dub3N0aWMgcm9sZSBvZiBjdEROQSBEeW5hbWljcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhJFJGUy5tb250aHM9Y2lyY19kYXRhJFJGUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRSRlMubW9udGhzPj0wLF0KY2lyY19kYXRhJFJGUy5tb250aHNbY2lyY19kYXRhJFJGUy5tb250aHMgPiA0OF0gPC0gNDgKY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpfmN0RE5BLkR5bmFtaWNzLCBkYXRhID0gY2lyY19kYXRhKQpldmVudF9zdW1tYXJ5IDwtIGNpcmNfZGF0YSAlPiUKICBncm91cF9ieShjdEROQS5EeW5hbWljcykgJT4lCiAgc3VtbWFyaXNlKAogICAgVG90YWwgPSBuKCksCiAgICBFdmVudHMgPSBzdW0oUkZTLkV2ZW50KSwKICAgIEZyYWN0aW9uID0gRXZlbnRzIC8gbigpLAogICAgUGVyY2VudGFnZSA9IChFdmVudHMgLyBuKCkpICogMTAwCiAgKQpwcmludChldmVudF9zdW1tYXJ5KQpzdXJ2X29iamVjdCA8LVN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpIApLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuRHluYW1pY3MsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT02LCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsInJlZCIpLCB0aXRsZT0iY3RETkEgRHluYW1pY3MgfCBQcmUtdHJlYXRtZW50IC0gT24tdHJlYXRtZW50IiwgeWxhYj0gIkRpc2Vhc2UgRnJlZSBTdXJ2aXZhbCIsIHhsYWI9IlRpbWUgZnJvbSBTdXJnZXJ5IChNb250aHMpIiwgbGVnZW5kLnRpdGxlPSIiKSAKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMTIsIDI0KSkKY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MsIGxldmVscz1jKCJQZXJzaXN0ZW50bHkgTmVnYXRpdmUiLCJDb252ZXJ0ZWQgTmVnYXRpdmUiLCJDb252ZXJ0ZWQgUG9zaXRpdmUiLCAiUGVyc2lzdGVudGx5IFBvc2l0aXZlIikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5EeW5hbWljcywgZGF0YT1jaXJjX2RhdGEpICAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpgYGAKCgojT1MgY3RETkEgRHluYW1pY3MKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSRPUy5tb250aHM9Y2lyY19kYXRhJE9TLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJE9TLm1vbnRocz49MCxdCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkT1MubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCl+Y3RETkEuRHluYW1pY3MsIGRhdGEgPSBjaXJjX2RhdGEpCmV2ZW50X3N1bW1hcnkgPC0gY2lyY19kYXRhICU+JQogIGdyb3VwX2J5KGN0RE5BLkR5bmFtaWNzKSAlPiUKICBzdW1tYXJpc2UoCiAgICBUb3RhbCA9IG4oKSwKICAgIEV2ZW50cyA9IHN1bShPUy5FdmVudCksCiAgICBGcmFjdGlvbiA9IEV2ZW50cyAvIG4oKSwKICAgIFBlcmNlbnRhZ2UgPSAoRXZlbnRzIC8gbigpKSAqIDEwMAogICkKcHJpbnQoZXZlbnRfc3VtbWFyeSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkT1MubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRPUy5FdmVudCkgCktNX2N1cnZlIDwtIHN1cnZmaXQoc3Vydl9vYmplY3QgfiBjdEROQS5EeW5hbWljcywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTYsIHBhbGV0dGU9YygicHVycGxlIiwiZ3JlZW4iLCJibHVlIiwicmVkIiksIHRpdGxlPSJNUkQgRHluYW1pY3MgfCBQcmUtdHJlYXRtZW50IC0gT24tdHJlYXRtZW50IiwgeWxhYj0gIk92ZXJhbGwgU3Vydml2YWwiLCB4bGFiPSJUaW1lIGZyb20gU3VyZ2VyeSAoTW9udGhzKSIsIGxlZ2VuZC50aXRsZT0iIikgCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDEyLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5EeW5hbWljcyA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzLCBsZXZlbHM9YygiUGVyc2lzdGVudGx5IE5lZ2F0aXZlIiwiQ29udmVydGVkIE5lZ2F0aXZlIiwiQ29udmVydGVkIFBvc2l0aXZlIiwgIlBlcnNpc3RlbnRseSBQb3NpdGl2ZSIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuRHluYW1pY3MsIGRhdGE9Y2lyY19kYXRhKSAgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKYGBgCgoKI09QIGZvciBwdHMgY29udmVydGVkIHBvc2l0aXZlIGR1cmluZyBBQ1QKYGBge3J9CnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjbGluc3RhZ2U8LSByZWFkLmNzdigiQVNBTl9DaG9sYW5naW9fT1AuY3N2IikKY2xpbnN0YWdlX2RmPC0gYXMuZGF0YS5mcmFtZShjbGluc3RhZ2UpCmNsaW5zdGFnZV9kZiA8LSBjbGluc3RhZ2VfZGZbY2xpbnN0YWdlX2RmJGN0RE5BLkR5bmFtaWNzPT0iQ29udmVydGVkIFBvc2l0aXZlIixdCgojI092ZXJ2aWV3IHBsb3QgLSBzdHJhdGlmaWVkIGJ5IFN0YWdlCm9wbG90X3N0cmF0aWZ5IDwtc3dpbW1lcl9wbG90KGRmPWNsaW5zdGFnZV9kZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ9J1BhdGllbnROYW1lJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kPSdmdS5kaWZmLm1vbnRocycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNuYW1lX2ZpbGw9J0FybScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbD0iZ3JheSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhPTAuNzUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoPS4wMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFzZV9zaXplID0gMTQpCm9wbG90X3N0cmF0aWZ5IDwtIG9wbG90X3N0cmF0aWZ5ICsgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpKQpvcGxvdF9zdHJhdGlmeSA8LSBvcGxvdF9zdHJhdGlmeSArIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgMTA4LCBieSA9IDYpKQpvcGxvdF9zdHJhdGlmeSA8LSBvcGxvdF9zdHJhdGlmeSArIGxhYnMoeCA9IlBhdGllbnRzIiAsIHk9Ik1vbnRocyBmcm9tIFN1cmdlcnkiKQpvcGxvdF9zdHJhdGlmeQoKIyNwbG90IGV2ZW50cwpvcGxvdF9ldjMgPC0gb3Bsb3Rfc3RyYXRpZnkgKyBzd2ltbWVyX3BvaW50cyhkZl9wb2ludHM9Y2xpbnN0YWdlX2RmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZD0nUGF0aWVudE5hbWUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lPSdkYXRlLmRpZmYubW9udGhzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZV9zaGFwZSA9J0V2ZW50X3R5cGUnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lX2NvbCA9ICdFdmVudCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9My41LGZpbGw9J2JsYWNrJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2NvbD0nZGFya2dyZWVuJwopCm9wbG90X2V2MwoKI1NoYXBlIGN1c3RvbWl6YXRpb24gdG8gRXZlbnRfdHlwZQoKb3Bsb3RfZXYzLjEgPC0gb3Bsb3RfZXYzICsgZ2dwbG90Mjo6c2NhbGVfc2hhcGVfbWFudWFsKG5hbWU9IkV2ZW50X3R5cGUiLHZhbHVlcz1jKDEsMTYsNiwxOCw0LCA1LCAyMywgNywgMTUpLGJyZWFrcz1jKCdjdEROQV9uZWcnLCAnY3RETkFfcG9zJywgJ0ltYWdpbmcnLCAnU3VyZ2VyeScsICdEZWF0aCcsICJjZWFfbmVnIiwgImNlYV9wb3MiLCAiY2ExOV9uZWciLCAiY2ExOV9wb3MiKSkKCm9wbG90X2V2My4xCgojcGxvdCB0cmVhdG1lbnQKCm9wbG90X2V2NCA8LSBvcGxvdF9ldjMuMSArIHN3aW1tZXJfbGluZXMoZGZfbGluZXM9Y2xpbnN0YWdlX2RmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkPSdQYXRpZW50TmFtZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQ9J1R4X3N0YXJ0Lm1vbnRocycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kPSdUeF9lbmQubW9udGhzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lX2NvbD0nVHhfdHlwZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT0zLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZV9hbHBoYSA9IDEuMCkKb3Bsb3RfZXY0IDwtIG9wbG90X2V2NCArIGd1aWRlcyhsaW5ldHlwZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA1LCBjb2xvciA9ICJibGFjayIpKSkKb3Bsb3RfZXY0ICAKCgojY29sb3VyIGN1c3RvbWl6YXRpb24KIyBvcmFuZ2U9QUNULCBCbGFjaz1EZWF0aCwgUmVkPVBELCBjdEROQSBuZWdhdGl2ZT13aGl0ZSwgY3RETkEgcG9zaXRpdmU9YmxhY2ssIFN1cmdlcnk9Ymx1ZSwgVFVSQlQ9Z3JheSAKb3Bsb3RfZXY0LjIgPC0gb3Bsb3RfZXY0ICsgZ2dwbG90Mjo6c2NhbGVfY29sb3JfbWFudWFsKG5hbWU9IkV2ZW50Iix2YWx1ZXM9YyggIm9yYW5nZSIsICJwdXJwbGUiLCAiYmx1ZSIsICJibGFjayIsICJibGFjayIsICJyZWQiLCAiYmx1ZSIsICJibHVlIikpCm9wbG90X2V2NC4yCmBgYAoKCiNjdEROQSBjbGVhcmFuY2UgcHJvcG9ydGlvbnMgYnkgY2hlbW90aGVyYXB5IHJlZ2ltZW4KYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJGN0RE5BLk1SRD09IlBPU0lUSVZFIixdCgpjaXJjX2RhdGEkY3RETkEuRHluYW1pY3MgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5EeW5hbWljcywgbGV2ZWxzID0gYygiQ29udmVydGVkIE5lZ2F0aXZlIiwgIlBlcnNpc3RlbnRseSBQb3NpdGl2ZSIpLCBsYWJlbHMgPSBjKCJDbGVhcmFuY2UiLCAiTm8gQ2xlYXJhbmNlIikpCmNpcmNfZGF0YSRDaGVtbyA8LSBmYWN0b3IoY2lyY19kYXRhJENoZW1vLCBsZXZlbHMgPSBjKCJDQVAiLCAiR2VtQ2lzIikpCmNvbnRpbmdlbmN5X3RhYmxlIDwtIHRhYmxlKGNpcmNfZGF0YSRDaGVtbywgY2lyY19kYXRhJGN0RE5BLkR5bmFtaWNzKQpjaGlfc3F1YXJlX3Rlc3QgPC0gY2hpc3EudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoY2hpX3NxdWFyZV90ZXN0KQpmaXNoZXJfZXhhY3RfdGVzdCA8LSBmaXNoZXIudGVzdChjb250aW5nZW5jeV90YWJsZSkKcHJpbnQoZmlzaGVyX2V4YWN0X3Rlc3QpCnByaW50KGNvbnRpbmdlbmN5X3RhYmxlKQp0YWJsZV9kZiA8LSBhcy5kYXRhLmZyYW1lKGNvbnRpbmdlbmN5X3RhYmxlKQp0YWJsZV9kZiRUb3RhbCA8LSBhdmUodGFibGVfZGYkRnJlcSwgdGFibGVfZGYkVmFyMSwgRlVOID0gc3VtKQp0YWJsZV9kZiRQZXJjZW50YWdlIDwtIHRhYmxlX2RmJEZyZXEgLyB0YWJsZV9kZiRUb3RhbAp0YWJsZV9kZiRNaWRkbGVQZXJjZW50YWdlIDwtIHRhYmxlX2RmJFBlcmNlbnRhZ2UgLyAyCmdncGxvdCh0YWJsZV9kZiwgYWVzKHggPSBWYXIxLCB5ID0gUGVyY2VudGFnZSwgZmlsbCA9IFZhcjIpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX3RleHQoYWVzKHkgPSBNaWRkbGVQZXJjZW50YWdlLCBsYWJlbCA9IEZyZXEpLCBwb3NpdGlvbiA9ICJzdGFjayIsIGNvbG9yID0gImJsYWNrIiwgdmp1c3QgPSAxLjUsIHNpemUgPSA3KSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gImN0RE5BIGNsZWFyYW5jZSBieSBSZWdpbWVuIiwgCiAgICAgICB4ID0gIlJlZ2ltZW4iLCAKICAgICAgIHkgPSAiUGF0aWVudHMgKCUpIiwgCiAgICAgICBmaWxsID0gImN0RE5BIENsZWFyYW5jZSIsCiAgICAgICBjYXB0aW9uID0gcGFzdGUoIkZpc2hlcidzIGV4YWN0IHRlc3QgcC12YWx1ZTogIiwgZm9ybWF0LnB2YWwoZmlzaGVyX2V4YWN0X3Rlc3QkcC52YWx1ZSkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkNsZWFyYW5jZSIgPSAiYmx1ZSIsICJObyBDbGVhcmFuY2UiID0gInJlZCIpKSArICMgZGVmaW5lIGN1c3RvbSBjb2xvcnMKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMS41LCBzaXplID0gMTQpLCAjIGluY3JlYXNlIHgtYXhpcyB0ZXh0IHNpemUKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeS1heGlzIHRleHQgc2l6ZQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGNvbG9yID0gImJsYWNrIiksICMgaW5jcmVhc2UgeC1heGlzIGxhYmVsIHNpemUKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJibGFjayIpLCAjIGluY3JlYXNlIHktYXhpcyBsYWJlbCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIpKSAgIyBpbmNyZWFzZSBQcm9ncmVzc2lvbiBsYWJlbCBzaXplCmBgYAoKCiNQcm9nbm9zdGljIHJvbGUgb2YgY3RETkEgQzVEMSBvbiBDaGVtb3RoZXJhcHkgLSA0IGdyb3VwcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsICFpcy5uYShjdEROQS5DNUQxKSkKY2lyY19kYXRhJFJGUy5tb250aHM9Y2lyY19kYXRhJFJGUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRSRlMubW9udGhzPj0wLF0KY2lyY19kYXRhJFJGUy5tb250aHNbY2lyY19kYXRhJFJGUy5tb250aHMgPiA2MF0gPC0gNjAKCgpjaXJjX2RhdGEkY3RETkEuQzVEMS5DaGVtbyA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5DNUQxLkNoZW1vID0gY2FzZV93aGVuKAogICAgQ2hlbW8gPT0gIkNBUCIgJiBjdEROQS5DNUQxID09ICJORUdBVElWRSIgfiAxLAogICAgQ2hlbW8gPT0gIkNBUCIgJiBjdEROQS5DNUQxID09ICJQT1NJVElWRSIgfiAyLAogICAgQ2hlbW8gPT0gIkdlbUNpcyIgJiBjdEROQS5DNUQxID09ICJORUdBVElWRSIgfiAzLAogICAgQ2hlbW8gPT0gIkdlbUNpcyIgJiBjdEROQS5DNUQxID09ICJQT1NJVElWRSIgfiA0CiAgKSkKY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpfmN0RE5BLkM1RDEuQ2hlbW8sIGRhdGEgPSBjaXJjX2RhdGEpCmV2ZW50X3N1bW1hcnkgPC0gY2lyY19kYXRhICU+JQogIGdyb3VwX2J5KGN0RE5BLkM1RDEuQ2hlbW8pICU+JQogIHN1bW1hcmlzZSgKICAgIFRvdGFsID0gbigpLAogICAgRXZlbnRzID0gc3VtKFJGUy5FdmVudCksCiAgICBGcmFjdGlvbiA9IEV2ZW50cyAvIG4oKSwKICAgIFBlcmNlbnRhZ2UgPSAoRXZlbnRzIC8gbigpKSAqIDEwMAogICkKcHJpbnQoZXZlbnRfc3VtbWFyeSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkUkZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkUkZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQzVEMS5DaGVtbywgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9IkRGUyAtIGN0RE5BIEM1RDEgJiBDaGVtb3RoZXJhcHkgUmVnaW1lbiIsIHlsYWI9ICJEaXNlYXNlIEZyZWUgU3Vydml2YWwiLCB4bGFiPSJNb250aHMgZnJvbSBzdXJnZXJ5IiwgbGVnZW5kLmxhYnM9YygiQ0FQICYgY3RETkEoLSkiLCAiQ0FQICYgY3RETkEoKykiLCJHZW1DaXMgJiBjdEROQSgtKSIsICJHZW1DaXMgJiBjdEROQSgrKSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsIDEyLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5DNUQxLkNoZW1vIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQzVEMS5DaGVtbywgbGV2ZWxzPWMoIjEiLCIyIiwiMyIsIjQiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkM1RDEuQ2hlbW8sIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQpgYGAKCgojUHJvZ25vc3RpYyByb2xlIG9mIGN0RE5BIEM4RDEgb24gQ2hlbW90aGVyYXB5IC0gNCBncm91cHMKYGBge3J9CnJtKGxpc3Q9bHMoKSkKc2V0d2QoIn4vRG93bmxvYWRzIikgCmNpcmNfZGF0YSA8LSByZWFkLmNzdigiQVNBTl9DbGluaWNhbERhdGFfR0xfMDgyMDIzLmNzdiIpCmNpcmNfZGF0YSA8LSBzdWJzZXQoY2lyY19kYXRhLCAhaXMubmEoY3RETkEuQzhEMSkpCmNpcmNfZGF0YSRSRlMubW9udGhzPWNpcmNfZGF0YSRSRlMubW9udGhzLTIKY2lyY19kYXRhIDwtIGNpcmNfZGF0YVtjaXJjX2RhdGEkUkZTLm1vbnRocz49MCxdCmNpcmNfZGF0YSRSRlMubW9udGhzW2NpcmNfZGF0YSRSRlMubW9udGhzID4gNjBdIDwtIDYwCgoKY2lyY19kYXRhJGN0RE5BLkM4RDEuQ2hlbW8gPC0gTkEgI2ZpcnN0IHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgZm9yIHRoZSBjdEROQSAmIE5BQyBjb21iaW5hdGlvbiwgYW5kIHdlIGFzc2lnbiB2YWx1ZXMKY2lyY19kYXRhIDwtIGNpcmNfZGF0YSAlPiUKICBtdXRhdGUoY3RETkEuQzhEMS5DaGVtbyA9IGNhc2Vfd2hlbigKICAgIENoZW1vID09ICJDQVAiICYgY3RETkEuQzhEMSA9PSAiTkVHQVRJVkUiIH4gMSwKICAgIENoZW1vID09ICJDQVAiICYgY3RETkEuQzhEMSA9PSAiUE9TSVRJVkUiIH4gMiwKICAgIENoZW1vID09ICJHZW1DaXMiICYgY3RETkEuQzhEMSA9PSAiTkVHQVRJVkUiIH4gMywKICAgIENoZW1vID09ICJHZW1DaXMiICYgY3RETkEuQzhEMSA9PSAiUE9TSVRJVkUiIH4gNAogICkpCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkUkZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkUkZTLkV2ZW50KX5jdEROQS5DOEQxLkNoZW1vLCBkYXRhID0gY2lyY19kYXRhKQpldmVudF9zdW1tYXJ5IDwtIGNpcmNfZGF0YSAlPiUKICBncm91cF9ieShjdEROQS5DOEQxLkNoZW1vKSAlPiUKICBzdW1tYXJpc2UoCiAgICBUb3RhbCA9IG4oKSwKICAgIEV2ZW50cyA9IHN1bShSRlMuRXZlbnQpLAogICAgRnJhY3Rpb24gPSBFdmVudHMgLyBuKCksCiAgICBQZXJjZW50YWdlID0gKEV2ZW50cyAvIG4oKSkgKiAxMDAKICApCnByaW50KGV2ZW50X3N1bW1hcnkpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLkM4RDEuQ2hlbW8sIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJwdXJwbGUiLCAicmVkIiksIHRpdGxlPSJERlMgLSBjdEROQSBDOEQxICYgQ2hlbW90aGVyYXB5IFJlZ2ltZW4iLCB5bGFiPSAiRGlzZWFzZSBGcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoIkNBUCAmIGN0RE5BKC0pIiwgIkNBUCAmIGN0RE5BKCspIiwiR2VtQ2lzICYgY3RETkEoLSkiLCAiR2VtQ2lzICYgY3RETkEoKykiKSwgbGVnZW5kLnRpdGxlPSIiKQpzdW1tYXJ5KEtNX2N1cnZlLCB0aW1lcz0gYygwLCAxMiwgMjQpKQpjaXJjX2RhdGEkY3RETkEuQzhEMS5DaGVtbyA8LSBmYWN0b3IoY2lyY19kYXRhJGN0RE5BLkM4RDEuQ2hlbW8sIGxldmVscz1jKCIxIiwiMiIsIjMiLCI0IikpCmNveF9maXQgPC0gY294cGgoc3Vydl9vYmplY3QgfiBjdEROQS5DOEQxLkNoZW1vLCBkYXRhPWNpcmNfZGF0YSkgCmdnZm9yZXN0KGNveF9maXQsZGF0YSA9IGNpcmNfZGF0YSkgCnN1bW1hcnkoY294X2ZpdCkKY294X2ZpdF9zdW1tYXJ5IDwtIHN1bW1hcnkoY294X2ZpdCkKYGBgCgoKI1Byb2dub3N0aWMgcm9sZSBvZiBjdEROQSBDNUQxIG9uIFByaW1hcnkgU2l0ZSAtIDQgZ3JvdXBzCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCJ+L0Rvd25sb2FkcyIpIApjaXJjX2RhdGEgPC0gcmVhZC5jc3YoIkFTQU5fQ2xpbmljYWxEYXRhX0dMXzA4MjAyMy5jc3YiKQpjaXJjX2RhdGEgPC0gc3Vic2V0KGNpcmNfZGF0YSwgIWlzLm5hKGN0RE5BLkM1RDEpKQpjaXJjX2RhdGEkUkZTLm1vbnRocz1jaXJjX2RhdGEkUkZTLm1vbnRocy0yCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGFbY2lyY19kYXRhJFJGUy5tb250aHM+PTAsXQpjaXJjX2RhdGEkUkZTLm1vbnRoc1tjaXJjX2RhdGEkUkZTLm1vbnRocyA+IDYwXSA8LSA2MAoKCmNpcmNfZGF0YSRjdEROQS5DNUQxLlByaW1TaXRlIDwtIE5BICNmaXJzdCB3ZSBjcmVhdGUgdGhlIHZhcmlhYmxlIGZvciB0aGUgY3RETkEgJiBOQUMgY29tYmluYXRpb24sIGFuZCB3ZSBhc3NpZ24gdmFsdWVzCmNpcmNfZGF0YSA8LSBjaXJjX2RhdGEgJT4lCiAgbXV0YXRlKGN0RE5BLkM1RDEuUHJpbVNpdGUgPSBjYXNlX3doZW4oCiAgICBQcmltU2l0ZSA9PSAiZENDQSIgJiBjdEROQS5DNUQxID09ICJORUdBVElWRSIgfiAxLAogICAgUHJpbVNpdGUgPT0gImRDQ0EiICYgY3RETkEuQzVEMSA9PSAiUE9TSVRJVkUiIH4gMiwKICAgIFByaW1TaXRlID09ICJwQ0NBIiAmIGN0RE5BLkM1RDEgPT0gIk5FR0FUSVZFIiB+IDMsCiAgICBQcmltU2l0ZSA9PSAicENDQSIgJiBjdEROQS5DNUQxID09ICJQT1NJVElWRSIgfiA0CiAgKSkKY2lyY19kYXRhZGYgPC0gYXMuZGF0YS5mcmFtZShjaXJjX2RhdGEpCgpzdXJ2Zml0KFN1cnYodGltZSA9IGNpcmNfZGF0YSRSRlMubW9udGhzLCBldmVudCA9IGNpcmNfZGF0YSRSRlMuRXZlbnQpfmN0RE5BLkM1RDEuUHJpbVNpdGUsIGRhdGEgPSBjaXJjX2RhdGEpCmV2ZW50X3N1bW1hcnkgPC0gY2lyY19kYXRhICU+JQogIGdyb3VwX2J5KGN0RE5BLkM1RDEuUHJpbVNpdGUpICU+JQogIHN1bW1hcmlzZSgKICAgIFRvdGFsID0gbigpLAogICAgRXZlbnRzID0gc3VtKFJGUy5FdmVudCksCiAgICBGcmFjdGlvbiA9IEV2ZW50cyAvIG4oKSwKICAgIFBlcmNlbnRhZ2UgPSAoRXZlbnRzIC8gbigpKSAqIDEwMAogICkKcHJpbnQoZXZlbnRfc3VtbWFyeSkKc3Vydl9vYmplY3QgPC1TdXJ2KHRpbWUgPSBjaXJjX2RhdGEkUkZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkUkZTLkV2ZW50KQpLTV9jdXJ2ZSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gY3RETkEuQzVEMS5QcmltU2l0ZSwgZGF0YSA9IGNpcmNfZGF0YSxjb25mLmludD0wLjk1LGNvbmYudHlwZT0ibG9nLWxvZyIpIApnZ3N1cnZwbG90KEtNX2N1cnZlLCBkYXRhID0gY2lyY19kYXRhLCBwdmFsID0gRkFMU0UsIGNvbmYuaW50ID0gRkFMU0UsIHJpc2sudGFibGUgPSBUUlVFLCBicmVhay50aW1lLmJ5PTEyLCBwYWxldHRlPWMoImJsdWUiLCJncmVlbiIsInB1cnBsZSIsICJyZWQiKSwgdGl0bGU9IkRGUyAtIGN0RE5BIEM1RDEgJiBQcmltYXJ5IFNpdGUiLCB5bGFiPSAiRGlzZWFzZSBGcmVlIFN1cnZpdmFsIiwgeGxhYj0iTW9udGhzIGZyb20gc3VyZ2VyeSIsIGxlZ2VuZC5sYWJzPWMoImRDQ0EgJiBjdEROQSgtKSIsICJkQ0NBICYgY3RETkEoKykiLCJwQ0NBICYgY3RETkEoLSkiLCAicENDQSAmIGN0RE5BKCspIiksIGxlZ2VuZC50aXRsZT0iIikKc3VtbWFyeShLTV9jdXJ2ZSwgdGltZXM9IGMoMCwgMTIsIDI0KSkKY2lyY19kYXRhJGN0RE5BLkM1RDEuUHJpbVNpdGUgPC0gZmFjdG9yKGNpcmNfZGF0YSRjdEROQS5DNUQxLlByaW1TaXRlLCBsZXZlbHM9YygiMSIsIjIiLCIzIiwiNCIpKQpjb3hfZml0IDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gY3RETkEuQzVEMS5QcmltU2l0ZSwgZGF0YT1jaXJjX2RhdGEpIApnZ2ZvcmVzdChjb3hfZml0LGRhdGEgPSBjaXJjX2RhdGEpIApzdW1tYXJ5KGNveF9maXQpCmNveF9maXRfc3VtbWFyeSA8LSBzdW1tYXJ5KGNveF9maXQpCmBgYAoKCiNQcm9nbm9zdGljIHJvbGUgb2YgY3RETkEgQzhEMSBvbiBQcmltYXJ5IFNpdGUgLSA0IGdyb3VwcwpgYGB7cn0Kcm0obGlzdD1scygpKQpzZXR3ZCgifi9Eb3dubG9hZHMiKSAKY2lyY19kYXRhIDwtIHJlYWQuY3N2KCJBU0FOX0NsaW5pY2FsRGF0YV9HTF8wODIwMjMuY3N2IikKY2lyY19kYXRhIDwtIHN1YnNldChjaXJjX2RhdGEsICFpcy5uYShjdEROQS5DOEQxKSkKY2lyY19kYXRhJFJGUy5tb250aHM9Y2lyY19kYXRhJFJGUy5tb250aHMtMgpjaXJjX2RhdGEgPC0gY2lyY19kYXRhW2NpcmNfZGF0YSRSRlMubW9udGhzPj0wLF0KY2lyY19kYXRhJFJGUy5tb250aHNbY2lyY19kYXRhJFJGUy5tb250aHMgPiA2MF0gPC0gNjAKCgpjaXJjX2RhdGEkY3RETkEuQzhEMS5QcmltU2l0ZSA8LSBOQSAjZmlyc3Qgd2UgY3JlYXRlIHRoZSB2YXJpYWJsZSBmb3IgdGhlIGN0RE5BICYgTkFDIGNvbWJpbmF0aW9uLCBhbmQgd2UgYXNzaWduIHZhbHVlcwpjaXJjX2RhdGEgPC0gY2lyY19kYXRhICU+JQogIG11dGF0ZShjdEROQS5DOEQxLlByaW1TaXRlID0gY2FzZV93aGVuKAogICAgUHJpbVNpdGUgPT0gImRDQ0EiICYgY3RETkEuQzhEMSA9PSAiTkVHQVRJVkUiIH4gMSwKICAgIFByaW1TaXRlID09ICJkQ0NBIiAmIGN0RE5BLkM4RDEgPT0gIlBPU0lUSVZFIiB+IDIsCiAgICBQcmltU2l0ZSA9PSAicENDQSIgJiBjdEROQS5DOEQxID09ICJORUdBVElWRSIgfiAzLAogICAgUHJpbVNpdGUgPT0gInBDQ0EiICYgY3RETkEuQzhEMSA9PSAiUE9TSVRJVkUiIH4gNAogICkpCmNpcmNfZGF0YWRmIDwtIGFzLmRhdGEuZnJhbWUoY2lyY19kYXRhKQoKc3VydmZpdChTdXJ2KHRpbWUgPSBjaXJjX2RhdGEkUkZTLm1vbnRocywgZXZlbnQgPSBjaXJjX2RhdGEkUkZTLkV2ZW50KX5jdEROQS5DOEQxLlByaW1TaXRlLCBkYXRhID0gY2lyY19kYXRhKQpldmVudF9zdW1tYXJ5IDwtIGNpcmNfZGF0YSAlPiUKICBncm91cF9ieShjdEROQS5DOEQxLlByaW1TaXRlKSAlPiUKICBzdW1tYXJpc2UoCiAgICBUb3RhbCA9IG4oKSwKICAgIEV2ZW50cyA9IHN1bShSRlMuRXZlbnQpLAogICAgRnJhY3Rpb24gPSBFdmVudHMgLyBuKCksCiAgICBQZXJjZW50YWdlID0gKEV2ZW50cyAvIG4oKSkgKiAxMDAKICApCnByaW50KGV2ZW50X3N1bW1hcnkpCnN1cnZfb2JqZWN0IDwtU3Vydih0aW1lID0gY2lyY19kYXRhJFJGUy5tb250aHMsIGV2ZW50ID0gY2lyY19kYXRhJFJGUy5FdmVudCkKS01fY3VydmUgPC0gc3VydmZpdChzdXJ2X29iamVjdCB+IGN0RE5BLkM4RDEuUHJpbVNpdGUsIGRhdGEgPSBjaXJjX2RhdGEsY29uZi5pbnQ9MC45NSxjb25mLnR5cGU9ImxvZy1sb2ciKSAKZ2dzdXJ2cGxvdChLTV9jdXJ2ZSwgZGF0YSA9IGNpcmNfZGF0YSwgcHZhbCA9IEZBTFNFLCBjb25mLmludCA9IEZBTFNFLCByaXNrLnRhYmxlID0gVFJVRSwgYnJlYWsudGltZS5ieT0xMiwgcGFsZXR0ZT1jKCJibHVlIiwiZ3JlZW4iLCJwdXJwbGUiLCAicmVkIiksIHRpdGxlPSJERlMgLSBjdEROQSBDOEQxICYgUHJpbWFyeSBTaXRlIiwgeWxhYj0gIkRpc2Vhc2UgRnJlZSBTdXJ2aXZhbCIsIHhsYWI9Ik1vbnRocyBmcm9tIHN1cmdlcnkiLCBsZWdlbmQubGFicz1jKCJkQ0NBICYgY3RETkEoLSkiLCAiZENDQSAmIGN0RE5BKCspIiwicENDQSAmIGN0RE5BKC0pIiwgInBDQ0EgJiBjdEROQSgrKSIpLCBsZWdlbmQudGl0bGU9IiIpCnN1bW1hcnkoS01fY3VydmUsIHRpbWVzPSBjKDAsIDEyLCAyNCkpCmNpcmNfZGF0YSRjdEROQS5DOEQxLlByaW1TaXRlIDwtIGZhY3RvcihjaXJjX2RhdGEkY3RETkEuQzhEMS5QcmltU2l0ZSwgbGV2ZWxzPWMoIjEiLCIyIiwiMyIsIjQiKSkKY294X2ZpdCA8LSBjb3hwaChzdXJ2X29iamVjdCB+IGN0RE5BLkM4RDEuUHJpbVNpdGUsIGRhdGE9Y2lyY19kYXRhKSAKZ2dmb3Jlc3QoY294X2ZpdCxkYXRhID0gY2lyY19kYXRhKSAKc3VtbWFyeShjb3hfZml0KQpjb3hfZml0X3N1bW1hcnkgPC0gc3VtbWFyeShjb3hfZml0KQpgYGAKCg==